Hi everyone,
I am trying to use the QueryBuilder with these options, but they seem to produce nothing, even when having a very generic Node-Node path. This is my example:
q = QueryBuilder()
q.append(Group, filters={'label':'group_label', tag='g')
q.append(WorkChainNode, with_group='g', tag='wc')
q.append(Node, with_ancestors='wc',)
No results are found. Am I interpreting it the right way? I don’t see why it produces nothing whatever is the Node
chosen (even generic Node
).
I think that the with_ancestors and with_descendants do not work with WorkChain
nodes (at least it does not work for me). It does work with data nodes, and CalcJob
nodes. I think that the explanation for why can be found here
1 Like
Thanks for pointing to this thread! It is indeed the usecase I would need.
Xing
April 27, 2024, 10:20am
4
I had the same issue recently. with_descendants
does not work with WorkChain
.
mbercx
April 28, 2024, 1:12pm
5
Indeed, the with_ancestors
and with_descendants
only work for the data provenance, not the logical provenance:
https://aiida.readthedocs.io/projects/aiida-core/en/stable/topics/provenance/concepts.html#data-provenance-and-logical-provenance
One critical difference between the two is that the data provenance is a directed acyclic graph (DAG). The logical provenance does allow for loops, for example the OutputInputWorkChain
example from the tutorials :
This can create issues with infinite loops for with_ancestors
and with_descendants
if you could use these when querying the logical provenance, as is noted by Leonid (the OG Querybuilder
developer, I believe) here:
opened 05:21PM - 14 Aug 20 UTC
type/bug
topic/query-builder
priority/nice-to-have
Code snippet that will trigger it:
```
from aiida import orm
from aiida.commo… n.links import LinkType
data = orm.Data().store()
calc = orm.CalculationNode().store()
data.add_incoming(calc, link_type=LinkType.CREATE, link_label='label')
builder = orm.QueryBuilder()
builder.append(orm.CalculationNode, tag='calculation')
builder.append(orm.Data, with_ancestors='calculation', edge_filters={'type': LinkType.CREATE.value})
builder.count()
```
the exception that is raised:
```
KeyError Traceback (most recent call last)
~/.virtualenvs/aiida_dev/lib/python3.7/site-packages/sqlalchemy/util/_collections.py in __getattr__(self, key)
209 try:
--> 210 return self._data[key]
211 except KeyError:
KeyError: 'type'
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
~/code/aiida/env/dev/aiida-core/aiida/orm/implementation/querybuilder.py in get_column(self, colname, alias)
400 try:
--> 401 return getattr(alias, colname)
402 except AttributeError:
~/.virtualenvs/aiida_dev/lib/python3.7/site-packages/sqlalchemy/util/_collections.py in __getattr__(self, key)
211 except KeyError:
--> 212 raise AttributeError(key)
213
AttributeError: type
During handling of the above exception, another exception occurred:
InputValidationError Traceback (most recent call last)
<ipython-input-1-cb9beeb4dffe> in <module>
11 builder.append(orm.Data, with_ancestors='calculation', edge_filters={'type': LinkType.CREATE.value})
12
---> 13 builder.count()
~/code/aiida/env/dev/aiida-core/aiida/orm/querybuilder.py in count(self)
2204 :returns: the number of rows as an integer
2205 """
-> 2206 query = self.get_query()
2207 return self._impl.count(query)
2208
~/code/aiida/env/dev/aiida-core/aiida/orm/querybuilder.py in get_query(self)
2100
2101 if need_to_build:
-> 2102 query = self._build()
2103 self._hash = queryhelp_hash
2104 else:
~/code/aiida/env/dev/aiida-core/aiida/orm/querybuilder.py in _build(self)
1950 'The tags I know are:\n{}'.format(tag, self.tag_to_alias_map.keys())
1951 )
-> 1952 self._query = self._query.filter(self._build_filters(alias, filter_specs))
1953
1954 ######################### PROJECTIONS ##########################
~/code/aiida/env/dev/aiida-core/aiida/orm/querybuilder.py in _build_filters(self, alias, filter_spec)
1373 is_attribute = (attr_key or column_name in ('attributes', 'extras'))
1374 try:
-> 1375 column = self._impl.get_column(column_name, alias)
1376 except InputValidationError:
1377 if is_attribute:
~/code/aiida/env/dev/aiida-core/aiida/orm/implementation/querybuilder.py in get_column(self, colname, alias)
405 'Valid columns are:\n'.format(
406 colname,
--> 407 alias # pylint: disable=protected-access
408 )
409 )
InputValidationError: type is not a column of ['%(140371970688720 anon)s.ancestor_id', '%(140371970688720 anon)s.descendant_id', 'anon_1.depth']
```
Note that I had to adapt the exception message of `get_column` itself, because it would also try to address an attribute of the `alias` variable, but the whole problem is that `alias` is not an instance of `Alias` but of `sqlalchemy.sql.base.ImmutableColumnCollection`.
@lekah I tried looking into this, but could really use your help here.
1 Like
As Leonid mentioned in the issue, maybe this is something to be solved not with the Query Builder directly but with the Graph Explorer? Maybe easiest to discuss at the AiiDA meeting the details and then report them back here? I also am not 100% sure anymore (but the graph explorer is used internally e.g. for finding all nodes to delete if one deletes one node, etc., and is efficient for this type of recursive queries)