Ejemplo n.º 1
0
def test_class():
    m = ObjectMap(cls=Node)
    assert isinstance(m, ObjectMap)
    assert m.cls.mapspec()["label"] == 'node'
    assert m.cls.attspec["props"] == 'collection'
    assert m.cls.attspec["_next"] == 'object'
    for c in (Node, Property, Term, Concept, Origin, Tag):
        assert isinstance(ObjectMap(cls=c), ObjectMap)
        assert c.mapspec()["label"] == c.__name__.lower()
Ejemplo n.º 2
0
def test_get(bento_neo4j):
    (b, h) = bento_neo4j
    drv = GraphDatabase.driver(b)
    assert drv
    node_map = ObjectMap(cls=Node, drv=drv)
    Node.object_map = node_map
    Concept.object_map = ObjectMap(cls=Concept, drv=drv)
    Property.object_map = ObjectMap(cls=Property, drv=drv)
    n_id = None
    with node_map.drv.session() as session:
        result = session.run("match (a:node) return id(a) limit 1")
        n_id = result.single().value()
    assert n_id
    node = Node()
    node.neoid = n_id
    node_map.get(node)
    assert node.dirty == 0
    assert node.__dict__['concept'].dirty == -1  # before dget()
    assert node.concept.dirty == 0  # after dget()
    assert node.concept._id == "a5b87a02-1eb3-4ec9-881d-f4479ab917ac"
    assert len(node.props) == 3
    assert node.props.data['site_short_name'].dirty == -1  # before dget()
    assert node.props['site_short_name'].dirty == 0  # after dget()
    assert node.props['site_short_name'].model == 'ICDC'
    concept = node.concept
    assert concept.belongs[(id(node), 'concept')] == node
    owners = node_map.get_owners(node)
    assert len(owners) == 1
    cncpt = Concept()
    Concept.object_map.get_by_id(cncpt, "a5b87a02-1eb3-4ec9-881d-f4479ab917ac")
    assert cncpt.terms[0] == concept.terms[0]
    pass
Ejemplo n.º 3
0
def test_rm_queries():
    m = ObjectMap(cls=FakeNode)
    n = FakeNode({"handle": "test", "model": "test_model", "category": 1})
    assert FakeNode.mapspec()["relationship"]["concept"]["end_cls"] == {
        "Concept", "Term"
    }
    with pytest.raises(ArgError, match="object must be mapped"):
        m.rm_q(n)
    n.neoid = 1
    qry = m.rm_q(n)
    assert qry == 'MATCH (n:node) WHERE id(n)=1 DELETE n'
    qry = m.rm_q(n, detach=True)
    assert qry == 'MATCH (n:node) WHERE id(n)=1 DETACH DELETE n'
    c = Concept({"_id": "blerf"})
    qry = m.rm_attr_q(n, 'model')
    assert qry == 'MATCH (n:node) WHERE id(n)=1 REMOVE n.model RETURN id(n)'
    qry = m.rm_attr_q(n, 'props', [':all'])
    assert qry == 'MATCH (n:node)-[r:has_property]->(a:property) WHERE id(n)=1 DELETE r RETURN id(n),id(a)'
    qry = m.rm_attr_q(n, 'concept', [':all'])
    assert re.match(
        "MATCH \\(n:node\\)-\\[r:has_concept\\]->\\(a\\) WHERE id\\(n\\)=1 AND \\('[a-z]+' IN labels\\(a\\) OR '[a-z]+' IN labels\\(a\\)\\) DELETE r",
        qry)
    prps = [
        Property(x) for x in ({
            "model": "test",
            "handle": "prop1"
        }, {
            "model": "test",
            "handle": "prop2"
        }, {
            "model": "test",
            "handle": "prop3"
        })
    ]
    i = 5
    for p in prps:
        p.neoid = i
        i += 1
    stmts = m.rm_attr_q(n, 'props', prps)
    assert stmts[
        0] == "MATCH (n:node)-[r:has_property]->(a:property) WHERE id(n)=1 AND id(a)=5 DELETE r RETURN id(n),id(a)"
    assert len(stmts) == 3
Ejemplo n.º 4
0
def test_get_model(bento_neo4j):
  (b,h)=bento_neo4j
  the_mdb = MDB(uri=b)
  assert the_mdb
  ObjectMap.clear_cache()
  m = Model(handle='ICDC',mdb=the_mdb)
  m.dget()

  with m.drv.session() as session:
    result = session.run('match (n:node) where n.model="ICDC" return count(n)')
    assert len(m.nodes) == result.single().value()
    result = session.run('match (n:relationship) where n.model="ICDC" return count(n)')
    assert len(m.edges) == result.single().value()
    result = session.run('match (p:property)<--(n:node) where p.model="ICDC" and  n.model="ICDC" return count(p)')
    assert len(m.props) == result.single().value()
    result = session.run(
      'match (s:node)<-[:has_src]-(e:relationship)-[:has_dst]->(d:node) where e.model="ICDC" return s,e,d')
    for rec in result:
      (s,e,d) = (rec['s'],rec['e'],rec['d'])
      triplet = (e['handle'], s['handle'], d['handle'])
      assert m.edges[triplet].handle == e['handle']
      assert m.edges[triplet].src.handle == s['handle']
      assert m.edges[triplet].dst.handle == d['handle']

    result = session.run(
      'match (n:node)-[:has_property]->(p:property) where (n.model="ICDC") return n, collect(p) as pp')
    for rec in result:
      for p in rec['pp']:
        key = (rec['n']['handle'], p['handle'])
        assert m.props[key]
        assert m.props[key].neoid == p.id
        assert m.nodes[rec['n']['handle']].props[p['handle']].neoid == p.id

    result = session.run(
      'match (t:term)<-[:has_term]-(v:value_set)<-[:has_value_set]-(p:property) where p.model="ICDC" return p, v, collect(t) as tt')
    for rec in result:
      (p, v, tt) = (rec['p'],rec['v'],rec['tt'])
      [op] = [ x for x in m.props.values() if x.handle == p['handle'] ]
      vs = op.value_set
      assert op
      assert set( op.values ) == { t['value'] for t in tt }
Ejemplo n.º 5
0
 def mdb(self, value):
     if isinstance(value, MDB):
         self._mdb = value
         for cls in (Node, Property, Edge, Term, ValueSet, Concept,
                     Predicate, Origin, Tag):
             cls.object_map = ObjectMap(cls=cls, drv=value.driver)
     elif not value:
         self._mdb = None
         for cls in (Node, Property, Edge, Term, ValueSet, Concept, Origin,
                     Tag):
             cls.object_map = None
     else:
         raise ArgError("mdb= arg must be a bento_meta.mdb.MDB object")
Ejemplo n.º 6
0
 def drv(self, value):
     if isinstance(value, (BoltDriver, Neo4jDriver)):
         self._drv = value
         for cls in (Node, Property, Edge, Term, ValueSet, Concept, Origin,
                     Tag):
             cls.object_map = ObjectMap(cls=cls, drv=value)
     elif not value:
         self._drv = None
         for cls in (Node, Property, Edge, Term, ValueSet, Concept, Origin,
                     Tag):
             cls.object_map = None
     else:
         raise ArgError(
             "drv= arg must be Neo4jDriver or BoltDriver (returned from GraphDatabase.driver())"
         )
Ejemplo n.º 7
0
def test_put_model(bento_neo4j):
  (b,h)=bento_neo4j
  the_mdb = MDB(uri=b)
  assert the_mdb
  ObjectMap.clear_cache()
  m = Model(handle='ICDC',mdb=the_mdb)
  m.dget()
  prop = m.props[('sample','sample_type')]
  sample = m.nodes['sample']
  edge = m.edges[('on_visit','sample', 'visit')]
  term = Term({"value":"electric_boogaloo"})
  m.add_terms(prop, term)
  node = m.nodes['lab_exam']
  m.dput()
  with m.drv.session() as session:
    result = session.run('match (v:value_set)-->(t:term {value:"electric_boogaloo"}) return v,t')
    rec = result.single()
    assert rec['v'].id == prop.value_set.neoid
    assert rec['t'].id == term.neoid
    assert rec['t']['value'] == term.value
    result = session.run('match (n:node {handle:"lab_exam"}) return n')
    rec = result.single()
    assert rec['n'].id == node.neoid

  term = m.props[('demographic','sex')].terms['M']
  assert term.concept
  assert term.concept._id == "337c0e4f-506a-4f4e-95f6-07c3462b81ff"

  concept = term.concept
  assert term in concept.belongs.values()
  term.concept=None
  assert not term in concept.belongs.values()
  assert ('concept',concept) in term.removed_entities
  m.dput()
  with m.drv.session() as session:
    result = session.run('match (t:term) where id(t)=$id return t',{"id":term.neoid})
    assert result.single() # term there
    result = session.run('match (c:concept) where id(c)=$id return c',{"id":concept.neoid})
    assert result.single() # concept there
    result = session.run('match (t:term)-->(c:concept) where id(t)=$id return t',{"id":term.neoid})
    assert not result.single() # but link is gone
  
    concept._id="heydude"
    term.concept = concept
    prop.model = None
    assert not prop.model

  m.dput()

  with m.drv.session() as session:
    result = session.run('match (t:term)--(c:concept) where id(t)=$id return c',{"id":term.neoid})
    s = result.single()
    assert s
    assert s['c'].id == concept.neoid
    assert s['c']['id'] == "heydude"
    result = session.run('match (p:property) where id(p)=$id return p',{"id":prop.neoid})
    s = result.single()
    assert s
    assert s['p'].id == prop.neoid
    assert not 'model' in s['p']

  prop.model = 'ICDC'
  at_enrollment = m.edges[('at_enrollment','prior_surgery','enrollment')]
  prior_surgery = m.nodes['prior_surgery']
  with m.drv.session() as session:
    result = session.run('match (n:node)<-[:has_src]-(r:relationship {handle:"at_enrollment"})-[:has_dst]->(:node {handle:"enrollment"}) where id(n)=$id return r',{"id":prior_surgery.neoid})
    s = result.single()
    assert s

  m.rm_edge(at_enrollment)
  assert not at_enrollment.src
  assert not at_enrollment.dst
  assert not at_enrollment in m.edges_out(prior_surgery)
  m.dput()
  with m.drv.session() as session:
    result = session.run('match (n:node)<-[:has_src]-(r:relationship {handle:"at_enrollment"})-[:has_dst]->(:node {handle:"enrollment"}) where id(n)=$id return r',{"id":prior_surgery.neoid})
    s = result.single()
    assert not s
    result = session.run('match (e:relationship) where id(e)=$id return e',{"id":at_enrollment.neoid})
    s = result.single()
    assert s
Ejemplo n.º 8
0
def test_put_rm(bento_neo4j):
    (b, h) = bento_neo4j
    drv = GraphDatabase.driver(b)
    vs_map = ObjectMap(cls=ValueSet, drv=drv)
    term_map = ObjectMap(cls=Term, drv=drv)
    vs = ValueSet({"_id": "narb"})
    terms = [Term({"value": x}) for x in ['quilm', 'ferb', 'narquit']]
    vs.terms = terms
    assert vs.terms['ferb'].value == 'ferb'
    vs_map.put(vs)
    rt = []
    with vs_map.drv.session() as session:
        result = session.run(
            "match (v:value_set)-[:has_term]->(t:term) where v.id='narb' return t order by t.value"
        )
        for rec in result:
            rt.append(rec['t']['value'])
    assert set(rt) == set(['ferb', 'narquit', 'quilm'])
    quilm = vs.terms['quilm']
    del vs.terms['quilm']
    assert len(vs.terms) == 2
    with pytest.raises(Neo4jError, match='.*Cannot delete'):
        term_map.rm(quilm)
    t_id = None
    with term_map.drv.session() as session:
        result = session.run("match (t:term {value:'quilm'}) return id(t)")
        t_id = result.single().value()
    assert t_id == quilm.neoid
    term_map.rm(quilm, 1)
    with term_map.drv.session() as session:
        result = session.run("match (t:term {value:'quilm'}) return id(t)")
        assert result.single() == None

    new_term = Term({"value": "belpit"})
    term_map.put(new_term)
    vs_map.add(vs, 'terms', new_term)
    assert len(vs.terms) == 2
    vs_map.get(vs, True)
    assert len(vs.terms) == 3
    assert vs.terms['belpit']
    old_term = vs.terms['ferb']
    r = None
    with term_map.drv.session() as session:
        result = session.run(
            "match (t:term {value:'ferb'})<-[r]-(v:value_set) return r")
        r = result.single().value()
        assert isinstance(r, neo4j.graph.Relationship)
    vs_map.drop(vs, 'terms', old_term)
    with term_map.drv.session() as session:
        result = session.run(
            "match (t:term {value:'ferb'})<-[r]-(v:value_set) return r")
        assert result.single() == None
    old_term = vs.terms['belpit']
Ejemplo n.º 9
0
    def dget(self, refresh=False):
        """Pull model from MDB into this Model instance, based on its handle

        Note: is a noop if `Model.drv` is unset.
        """
        if not self.drv:
            return
        if refresh:
            ObjectMap.clear_cache()
        with self.drv.session() as session:
            result = session.run(
                "match p = (s:node)<-[:has_src]-(r:relationship)-[:has_dst]->(d:node) "
                "where s.model=$hndl and r.model=$hndl and d.model=$hndl return p",
                {"hndl": self.handle},
            )
            for rec in result:
                (ns, nr, nd) = rec["p"].nodes
                ns = Node(ns)
                nr = Edge(nr)
                nd = Node(nd)
                ObjectMap.cache[ns.neoid] = ns
                ObjectMap.cache[nr.neoid] = nr
                ObjectMap.cache[nd.neoid] = nd
                nr.src = ns
                nr.dst = nd
                self.nodes[ns.handle] = ns
                self.nodes[nd.handle] = nd
                self.edges[nr.triplet] = nr

        with self.drv.session() as session:
            result = session.run(
                "match (n:node)-[:has_property]->(p:property) where n.model=$hndl and p.model=$hndl return id(n), p",
                {"hndl": self.handle},
            )
            for rec in result:
                n = ObjectMap.cache.get(rec["id(n)"])
                if n is None:
                    warn("node with id {nid} not yet retrieved".format(
                        nid=rec["id(n)"]))
                    continue
                p = Property(rec["p"])
                ObjectMap.cache[p.neoid] = p
                self.props[(n.handle, p.handle)] = p
                n.props[p.handle] = p
                p.dirty = -1
        with self.drv.session() as session:
            result = session.run(
                "match (r:relationship)-[:has_property]->(p:property) "
                "where r.model=$hndl and p.model=$hndl return id(r), p",
                {"hndl": self.handle},
            )
            for rec in result:
                e = ObjectMap.cache.get(rec["id(r)"])
                if e is None:
                    warn("relationship with id {rid} not yet retrieved".format(
                        rid=rec["id(r)"]))
                    continue
                p = Property(rec["p"])
                ObjectMap.cache[p.neoid] = p
                k = list(e.triplet)
                k.append(p.handle)
                self.props[tuple(k)] = p
                e.props[p.handle] = p
                p.dirty = -1
        return self
Ejemplo n.º 10
0
from bento_meta.object_map import ObjectMap
from bento_meta.objects import *
from warnings import warn
from pdb import set_trace
from neo4j import GraphDatabase
import csv
import uuid

port= sys.argv[1] if len(sys.argv) > 1 else 7687
bolt_url = 'bolt://localhost:{}'.format(port)
try:
    drv = GraphDatabase.driver(bolt_url) if bolt_url else None
except:
    drv = None
    
origin_om = ObjectMap(cls=Origin,drv=drv);
term_om = ObjectMap(cls=Term,drv=drv)
concept_om = ObjectMap(cls=Concept,drv=drv)

# create local origin objects for terms
origins = {"icdc":Origin({"name":"ICDC"}),
  "ctdc":Origin({"name":"CTDC"}),
  "bento":Origin({"name":"Bento"}),
  "ncit":Origin({"name":"NCIt"}) }
  

# latest MDF for each model

mdf = {
  "bento":[
    "https://cbiit.github.io/bento-model/model-desc/bento_model_file.yaml",
Ejemplo n.º 11
0
def test_put_queries():
    m = ObjectMap(cls=Node)
    n = Node({"handle": "test", "model": "test_model", "_commit": 1})
    qry = m.put_q(n)
    assert qry == [
        'CREATE (n:node {_commit:1,handle:"test",model:"test_model"}) RETURN n,id(n)'
    ]
    n.neoid = 2
    stmts = m.put_q(n)
    assert stmts[
        0] == 'MATCH (n:node) WHERE id(n)=2 SET n._commit=1,n.handle="test",n.model="test_model" RETURN n,id(n)'
    assert len(stmts[1:]) == len(
        [x for x in Node.attspec if Node.attspec[x] == 'simple']) - 3
    for s in stmts[1:]:
        assert re.match(
            '^MATCH \\(n:node\\) WHERE id\\(n\\)=2 REMOVE n.[a-z_]+ RETURN n,id\\(n\\)$',
            s)
    n.neoid = None
    with pytest.raises(ArgError, match='object must be mapped'):
        m.put_attr_q(n, '_commit', 2)
    n.neoid = 1
    c = Concept({"_id": "blarf"})
    with pytest.raises(
            ArgError,
            match="'values' must be a list of mapped Entity objects"):
        m.put_attr_q(n, 'concept', c)
    with pytest.raises(
            ArgError,
            match="'values' must be a list of mapped Entity objects"):
        m.put_attr_q(n, 'concept', [c])
    qry = m.put_attr_q(n, '_commit', [3])
    assert qry == "MATCH (n:node) WHERE id(n)=1 SET _commit=3 RETURN id(n)"
    c.neoid = 2
    stmts = m.put_attr_q(n, 'concept', [c])
    assert stmts[
        0] == "MATCH (n:node),(a:concept) WHERE id(n)=1 AND id(a)=2 MERGE (n)-[:has_concept]->(a) RETURN id(a)"
    assert len(stmts) == 1
    prps = [
        Property(x) for x in ({
            "model": "test",
            "handle": "prop1"
        }, {
            "model": "test",
            "handle": "prop2"
        }, {
            "model": "test",
            "handle": "prop3"
        })
    ]
    i = 5
    for p in prps:
        p.neoid = i
        i += 1
    stmts = m.put_attr_q(n, 'props', prps)
    assert stmts[
        0] == "MATCH (n:node),(a:property) WHERE id(n)=1 AND id(a)=5 MERGE (n)-[:has_property]->(a) RETURN id(a)"
    assert len(stmts) == 3
    m = ObjectMap(cls=FakeNode)
    n = FakeNode({"handle": "test", "model": "test_model", "category": 1})
    n.neoid = 1
    t = Term({"value": "boog"})
    t.neoid = 6
    stmts = m.put_attr_q(n, "concept", [t])
    assert re.match(
        "MATCH \\(n:node\\),\\(a\\) WHERE id\\(n\\)=1 AND id\\(a\\)=6 AND \\('[a-z]+' IN labels\\(a\\) OR '[a-z]+' IN labels\\(a\\)\\) MERGE \\(n\\)-\\[:has_concept\\]->\\(a\\) RETURN id\\(a\\)",
        stmts[0])
    qry = m.get_attr_q(n, "concept")
    assert re.match(
        "MATCH \\(n:node\\)-\\[:has_concept\\]->\\(a\\) WHERE id\\(n\\)=1 AND \\('[a-z]+' IN labels\\(a\\) OR '[a-z]+' IN labels\\(a\\)\\) RETURN a",
        qry)
    pass
Ejemplo n.º 12
0
def test_get_queries():
    m = ObjectMap(cls=Node)
    with pytest.raises(ArgError, match='arg1 must be object of class'):
        m.get_q(ValueSet())
    with pytest.raises(ArgError, match='object must be mapped'):
        m.get_q(Node())
    n = Node({"handle": "test", "model": "test"})
    n.neoid = 1
    qry = m.get_q(n)
    assert qry == "MATCH (n:node) WHERE id(n)=1 RETURN n,id(n)"
    with pytest.raises(ArgError,
                       match="'flerb' is not a registered attribute"):
        m.get_attr_q(n, 'flerb')
    qry = m.get_attr_q(n, 'model')
    assert qry == "MATCH (n:node) WHERE id(n)=1 RETURN n.model"
    qry = m.get_attr_q(n, 'props')
    assert qry == "MATCH (n:node)-[:has_property]->(a:property) WHERE id(n)=1 RETURN a"
    qry = m.get_attr_q(n, 'concept')
    assert qry == "MATCH (n:node)-[:has_concept]->(a:concept) WHERE id(n)=1 RETURN a LIMIT 1"
Ejemplo n.º 13
0
def test_put_then_rm_queries():
    """test adding then removing attr"""
    m = ObjectMap(cls=Node)
    n = Node({"handle": "test_", "model": "test_model_", "_commit": 1})
    qry = m.put_q(n)
    assert qry == [
        'CREATE (n:node {_commit:1,handle:"test_",model:"test_model_"}) RETURN n,id(n)'
    ]

    # manually set neoid
    n.neoid = 2
    stmts = m.put_q(n)
    assert stmts[
        0] == 'MATCH (n:node) WHERE id(n)=2 SET n._commit=1,n.handle="test_",n.model="test_model_" RETURN n,id(n)'
    assert len(stmts[1:]) == len(
        [x for x in Node.attspec if Node.attspec[x] == 'simple']) - 3
    for s in stmts[1:]:
        assert re.match(
            '^MATCH \\(n:node\\) WHERE id\\(n\\)=2 REMOVE n.[a-z_]+ RETURN n,id\\(n\\)$',
            s)

    n.neoid = None
    with pytest.raises(ArgError, match='object must be mapped'):
        m.put_attr_q(n, '_commit', 2)

    n.neoid = 1
    c = Concept({"_id": "blarfblark"})
    with pytest.raises(
            ArgError,
            match="'values' must be a list of mapped Entity objects"):
        m.put_attr_q(n, 'concept', c)
    with pytest.raises(
            ArgError,
            match="'values' must be a list of mapped Entity objects"):
        m.put_attr_q(n, 'concept', [c])

    qry = m.put_attr_q(n, '_commit', [3])
    assert qry == "MATCH (n:node) WHERE id(n)=1 SET _commit=3 RETURN id(n)"

    c.neoid = 2
    stmts = m.put_attr_q(n, 'concept', [c])
    #assert stmts[0] == "MATCH (n:node),(a:concept) WHERE id(n)=1 AND id(a)=2 MERGE (n)-[:has_concept]->(a) RETURN id(a)"
    assert len(stmts) == 1

    prps = [
        Property(x) for x in ({
            "model": "test_",
            "handle": "prop1"
        }, {
            "model": "test_",
            "handle": "prop2"
        }, {
            "model": "test_",
            "handle": "prop3"
        })
    ]
    i = 5
    for p in prps:
        p.neoid = i
        i += 1
    stmts = m.put_attr_q(n, 'props', prps)
    assert stmts[
        0] == "MATCH (n:node),(a:property) WHERE id(n)=1 AND id(a)=5 MERGE (n)-[:has_property]->(a) RETURN id(a)"
    assert len(stmts) == 3
    Node.mapspec_ = {
        "label": "node",
        "property": {
            "handle": "handle",
            "model": "model"
        },
        "relationship": {
            "concept": {
                "rel": ":has_concept>",
                "end_cls": {"Concept", "Term"}
            },
            "props": {
                "rel": ":has_property>",
                "end_cls": "Property"
            }
        }
    }
    (Node.attspec, Node._mapspec) = mergespec('Node', Node.attspec,
                                              Node.mapspec_)
    assert Node.mapspec()["relationship"]["concept"]["end_cls"] == {
        "Concept", "Term"
    }
    t = Term({"value": "boogblark"})
    t.neoid = 6
    stmts = m.put_attr_q(n, "concept", [t])
    assert re.match(
        "MATCH \\(n:node\\),\\(a\\) WHERE id\\(n\\)=1 AND id\\(a\\)=6 AND \\('[a-z]+' IN labels\\(a\\) OR '[a-z]+' IN labels\\(a\\)\\) MERGE \\(n\\)-\\[:has_concept\\]->\\(a\\) RETURN id\\(a\\)",
        stmts[0])
    qry = m.get_attr_q(n, "concept")
    assert re.match(
        "MATCH \\(n:node\\)-\\[:has_concept\\]->\\(a\\) WHERE id\\(n\\)=1 AND \\('[a-z]+' IN labels\\(a\\) OR '[a-z]+' IN labels\\(a\\)\\) RETURN a",
        qry)

    # now delete the attr I just added....
    qry2 = m.rm_attr_q(n, "concept", [t])
    assert re.match(
        "MATCH \\(n:node\\)-\\[r:has_concept\\]->\\(a\\) WHERE id\\(n\\)=1 AND id\\(a\\)=6 AND \\('[a-z]+' IN labels\\(a\\) OR '[a-z]+' IN labels\\(a\\)\\) DELETE r RETURN id\\(n\\),id\\(a\\)",
        qry2[0])