def test_joins1(self): from aiida.orm import Node, Data, Calculation from aiida.orm.querybuilder import QueryBuilder # Creating n1, who will be a parent: parent=Node() parent.label = 'mother' good_child=Node() good_child.label='good_child' good_child._set_attr('is_good', True) bad_child=Node() bad_child.label='bad_child' bad_child._set_attr('is_good', False) unrelated = Node() unrelated.label = 'unrelated' for n in (good_child, bad_child, parent, unrelated): n.store() good_child.add_link_from(parent, label='parent') bad_child.add_link_from(parent, label='parent') # Using a standard inner join qb = QueryBuilder() qb.append(Node, tag='parent') qb.append(Node, tag='children', project='label', filters={'attributes.is_good':True}) self.assertEqual(qb.count(), 1) qb = QueryBuilder() qb.append(Node, tag='parent') qb.append(Node, tag='children', outerjoin=True, project='label', filters={'attributes.is_good':True}) self.assertEqual(qb.count(), 1)
def test_query_path(self): from aiida.orm.querybuilder import QueryBuilder from aiida.orm import Node n1 = Node() n1.label='n1' n1.store() n2 = Node() n2.label='n2' n2.store() n3 = Node() n3.label='n3' n3.store() n4 = Node() n4.label='n4' n4.store() n5 = Node() n5.label='n5' n5.store() n6 = Node() n6.label='n6' n6.store() n7 = Node() n7.label='n7' n7.store() n8 = Node() n8.label='n8' n8.store() n9 = Node() n9.label='n9' n9.store() # I create a strange graph, inserting links in a order # such that I often have to create the transitive closure # between two graphs n3.add_link_from(n2) n2.add_link_from(n1) n5.add_link_from(n3) n5.add_link_from(n4) n4.add_link_from(n2) n7.add_link_from(n6) n8.add_link_from(n7) for with_dbpath in (True, False): # Yet, no links from 1 to 8 self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n1.pk}, tag='anc' ).append(Node, descendant_of='anc', filters={'id':n8.pk} ).count(), 0) self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n8.pk}, tag='desc' ).append(Node, ancestor_of='desc', filters={'id':n1.pk} ).count(), 0) n6.add_link_from(n5) # Yet, now 2 links from 1 to 8 for with_dbpath in (True, False): self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n1.pk}, tag='anc' ).append(Node, descendant_of='anc', filters={'id':n8.pk} ).count(), 2 ) self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n8.pk}, tag='desc' ).append(Node, ancestor_of='desc', filters={'id':n1.pk} ).count(), 2) qb = QueryBuilder(with_dbpath=False,expand_path=True).append( Node, filters={'id':n8.pk}, tag='desc', ).append(Node, ancestor_of='desc', edge_project='path', filters={'id':n1.pk}) queried_path_set = set([frozenset(p) for p, in qb.all()]) paths_there_should_be = set([ frozenset([n1.pk, n2.pk, n3.pk, n5.pk, n6.pk, n7.pk, n8.pk]), frozenset([n1.pk, n2.pk, n4.pk, n5.pk, n6.pk, n7.pk, n8.pk]) ]) self.assertTrue(queried_path_set == paths_there_should_be) qb = QueryBuilder(with_dbpath=False, expand_path=True).append( Node, filters={'id':n1.pk}, tag='anc' ).append( Node, descendant_of='anc', filters={'id':n8.pk}, edge_project='path' ) self.assertTrue(set( [frozenset(p) for p, in qb.all()] ) == set( [frozenset([n1.pk, n2.pk, n3.pk, n5.pk, n6.pk, n7.pk, n8.pk]), frozenset([n1.pk, n2.pk, n4.pk, n5.pk, n6.pk, n7.pk, n8.pk])] )) n7.add_link_from(n9) # Still two links... for with_dbpath in (True, False): self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n1.pk}, tag='anc' ).append(Node, descendant_of='anc', filters={'id':n8.pk} ).count(), 2 ) self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n8.pk}, tag='desc' ).append(Node, ancestor_of='desc', filters={'id':n1.pk} ).count(), 2) n9.add_link_from(n6) # And now there should be 4 nodes for with_dbpath in (True, False): self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n1.pk}, tag='anc' ).append(Node, descendant_of='anc', filters={'id':n8.pk} ).count(), 4) self.assertEquals( QueryBuilder(with_dbpath=with_dbpath).append( Node, filters={'id':n8.pk}, tag='desc' ).append(Node, ancestor_of='desc', filters={'id':n1.pk} ).count(), 4) for with_dbpath in (True, False): qb = QueryBuilder(with_dbpath=True).append( Node, filters={'id':n1.pk}, tag='anc' ).append( Node, descendant_of='anc', filters={'id':n8.pk}, edge_tag='edge' ) qb.add_projection('edge', 'depth') self.assertTrue(set(zip(*qb.all())[0]), set([5,6])) qb.add_filter('edge', {'depth':6}) self.assertTrue(set(zip(*qb.all())[0]), set([6]))
def test_simple_query_2(self): from aiida.orm.querybuilder import QueryBuilder from aiida.orm import Node from datetime import datetime from aiida.common.exceptions import MultipleObjectsError, NotExistent n0 = Node() n0.label = 'hello' n0.description='' n0._set_attr('foo', 'bar') n1 = Node() n1.label='foo' n1.description='I am FoO' n2 = Node() n2.label='bar' n2.description='I am BaR' n2.add_link_from(n1, label='random_2') n1.add_link_from(n0, label='random_1') for n in (n0, n1, n2): n.store() qb1 = QueryBuilder() qb1.append(Node, filters={'label': 'hello'}) self.assertEqual(len(list(qb1.all())), 1) qh = { 'path': [ { 'cls': Node, 'tag': 'n1' }, { 'cls': Node, 'tag': 'n2', 'output_of': 'n1' } ], 'filters': { 'n1': { 'label': {'ilike': '%foO%'}, }, 'n2': { 'label': {'ilike': 'bar%'}, } }, 'project': { 'n1': ['id', 'uuid', 'ctime', 'label'], 'n2': ['id', 'description', 'label'], } } qb2 = QueryBuilder(**qh) resdict = qb2.dict() self.assertEqual(len(resdict), 1) self.assertTrue(isinstance(resdict[0]['n1']['ctime'], datetime)) res_one = qb2.one() self.assertTrue('bar' in res_one) qh = { 'path': [ { 'cls': Node, 'tag': 'n1' }, { 'cls': Node, 'tag': 'n2', 'output_of': 'n1' } ], 'filters': { 'n1--n2': {'label': {'like': '%_2'}} } } qb = QueryBuilder(**qh) self.assertEqual(qb.count(), 1) # Test the hashing: query1 = qb.get_query() qb.add_filter('n2', {'label': 'nonexistentlabel'}) self.assertEqual(qb.count(), 0) with self.assertRaises(NotExistent): qb.one() with self.assertRaises(MultipleObjectsError): QueryBuilder().append(Node).one() query2 = qb.get_query() query3 = qb.get_query() self.assertTrue(id(query1) != id(query2)) self.assertTrue(id(query2) == id(query3))
def test_query_path(self): from aiida.orm.querybuilder import QueryBuilder from aiida.orm import Node from aiida.common.links import LinkType from aiida.backends.utils import QueryFactory q = QueryFactory()() n1 = Node() n1.label = 'n1' n1.store() n2 = Node() n2.label = 'n2' n2.store() n3 = Node() n3.label = 'n3' n3.store() n4 = Node() n4.label = 'n4' n4.store() n5 = Node() n5.label = 'n5' n5.store() n6 = Node() n6.label = 'n6' n6.store() n7 = Node() n7.label = 'n7' n7.store() n8 = Node() n8.label = 'n8' n8.store() n9 = Node() n9.label = 'n9' n9.store() # I create a strange graph, inserting links in a order # such that I often have to create the transitive closure # between two graphs # I set everything as an INPUT-links now, because the QueryBuilder path query or # our custom queries don't follow other links than CREATE or INPUT n3.add_link_from(n2, link_type=LinkType.INPUT) n2.add_link_from(n1, link_type=LinkType.INPUT) n5.add_link_from(n3, link_type=LinkType.INPUT) n5.add_link_from(n4, link_type=LinkType.INPUT) n4.add_link_from(n2, link_type=LinkType.INPUT) n7.add_link_from(n6, link_type=LinkType.INPUT) n8.add_link_from(n7, link_type=LinkType.INPUT) # There are no parents to n9, checking that self.assertEqual(set([]), set(q.get_all_parents([n9.pk]))) # There is one parent to n6 self.assertEqual(set([(_, ) for _ in (n6.pk, )]), set([tuple(_) for _ in q.get_all_parents([n7.pk])])) # There are several parents to n4 self.assertEqual(set([(_.pk, ) for _ in (n1, n2)]), set([tuple(_) for _ in q.get_all_parents([n4.pk])])) # There are several parents to n5 self.assertEqual(set([(_.pk, ) for _ in (n1, n2, n3, n4)]), set([tuple(_) for _ in q.get_all_parents([n5.pk])])) # Yet, no links from 1 to 8 self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n1.pk }, tag='anc').append(Node, descendant_of='anc', filters={ 'id': n8.pk }).count(), 0) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append(Node, ancestor_of='desc', filters={ 'id': n1.pk }).count(), 0) n6.add_link_from(n5, link_type=LinkType.INPUT) # Yet, now 2 links from 1 to 8 self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n1.pk }, tag='anc').append(Node, descendant_of='anc', filters={ 'id': n8.pk }).count(), 2) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append(Node, ancestor_of='desc', filters={ 'id': n1.pk }).count(), 2) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append( Node, ancestor_of='desc', filters={ 'id': n1.pk }, edge_filters={ 'depth': { '<': 6 } }, ).count(), 2) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append( Node, ancestor_of='desc', filters={ 'id': n1.pk }, edge_filters={ 'depth': 5 }, ).count(), 2) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append( Node, ancestor_of='desc', filters={ 'id': n1.pk }, edge_filters={ 'depth': { '<': 5 } }, ).count(), 0) # TODO write a query that can filter certain paths by traversed ID qb = QueryBuilder().append( Node, filters={ 'id': n8.pk }, tag='desc', ).append(Node, ancestor_of='desc', edge_project='path', filters={'id': n1.pk}) queried_path_set = set([frozenset(p) for p, in qb.all()]) paths_there_should_be = set([ frozenset([n1.pk, n2.pk, n3.pk, n5.pk, n6.pk, n7.pk, n8.pk]), frozenset([n1.pk, n2.pk, n4.pk, n5.pk, n6.pk, n7.pk, n8.pk]) ]) self.assertTrue(queried_path_set == paths_there_should_be) qb = QueryBuilder().append(Node, filters={ 'id': n1.pk }, tag='anc').append(Node, descendant_of='anc', filters={'id': n8.pk}, edge_project='path') self.assertTrue( set([frozenset(p) for p, in qb.all()]) == set([ frozenset([n1.pk, n2.pk, n3.pk, n5.pk, n6.pk, n7.pk, n8.pk]), frozenset([n1.pk, n2.pk, n4.pk, n5.pk, n6.pk, n7.pk, n8.pk]) ])) n7.add_link_from(n9, link_type=LinkType.INPUT) # Still two links... self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n1.pk }, tag='anc').append(Node, descendant_of='anc', filters={ 'id': n8.pk }).count(), 2) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append(Node, ancestor_of='desc', filters={ 'id': n1.pk }).count(), 2) n9.add_link_from(n6, link_type=LinkType.INPUT) # And now there should be 4 nodes self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n1.pk }, tag='anc').append(Node, descendant_of='anc', filters={ 'id': n8.pk }).count(), 4) self.assertEquals( QueryBuilder().append(Node, filters={ 'id': n8.pk }, tag='desc').append(Node, ancestor_of='desc', filters={ 'id': n1.pk }).count(), 4) qb = QueryBuilder().append(Node, filters={ 'id': n1.pk }, tag='anc').append(Node, descendant_of='anc', filters={'id': n8.pk}, edge_tag='edge') qb.add_projection('edge', 'depth') self.assertTrue(set(zip(*qb.all())[0]), set([5, 6])) qb.add_filter('edge', {'depth': 6}) self.assertTrue(set(zip(*qb.all())[0]), set([6]))