def _fetch(cls, match_spec, params=None): if params is None: params = {} query = graph.construct_query(match_spec=match_spec, return_spec=cls._fetch_fields) qret = graph.query(query, **params) return qret
def add_relation(cls, src, dst, rel_class, rel_attrs=None, _global=False): query = """ MATCH (src:Instance) WHERE id(src) = $src_id MATCH (dst:Instance) WHERE id(dst) = $dst_id MATCH (relcls:RelationClass { name: $rel_clsname }) MERGE (src)-[:from]->(rel:Thing:RelationInstance:`%s`)-[:to]->(dst) ON CREATE SET rel += $rel_attrs ON MATCH SET rel += {clobbered: true} MERGE (rel)-[:instance_of]->(relcls) WITH src, dst, rel CALL apoc.create.addLabels(rel, [ $rel_clsname ]) YIELD node AS n_rel RETURN src, dst, n_rel; """ % (rel_class) # TODO: handle _global here properly assert src._id is not None assert dst._id is not None if rel_attrs is None: rel_attrs = {} assert src._oid is not None assert dst._oid is not None rel_attrs.setdefault('_oid', str(uuid_edgehash(src._oid, dst._oid))) LOG.debug('add-relation, query=%r' % query) qret = graph.query(query, src_id=src._id, dst_id=dst._id, rel_attrs=rel_attrs, rel_clsname=rel_class) LOG.debug('add-relation returned=%r' % qret) return qret
def create(self, _global=False): query = """ MATCH (cls:Class { name: $cls_name }) MERGE (inst:Thing:Instance { _oid: $inst_oid })-[:instance_of]->(cls) SET inst = $inst_props WITH cls, inst CALL apoc.create.addLabels(inst, $inst_labels) YIELD node as n_inst RETURN id(n_inst) as inst_id, n_inst as inst; """ obj_props = self._get_props() obj_labels = [self.instance_of] is_global = _global or self._global if is_global: obj_labels.append('Global') assert obj_props['_oid'] is not None else: obj_labels.append('Local') if obj_props.get('_oid', None) is None: obj_props['_oid'] = str(uuid.uuid4()) qret = graph.query(query, inst_oid=obj_props['_oid'], cls_name=self.instance_of, inst_labels=obj_labels, inst_props=obj_props) assert len(qret) == 1 retobj = qret[0]['inst'] self._id = qret[0]['inst_id'] self._oid = retobj['_oid'] LOG.debug('oid set to %r (retob=%r)' % (self._oid, retobj)) return self
def delete_by_id(cls, inst_id): ret = graph.query(''' MATCH (x:Instance) WHERE id(x) = $inst_id OPTIONAL MATCH (x)-[:to|from]-(ri:RelationInstance)-[:to|from]-() DETACH DELETE x, ri; ''', inst_id=inst_id) return ret
def create_instances(): LOG.debug('create_instances()') LOG.debug('create_instances() deleting existing global instances') graph.query("MATCH (x:Global:Instance) DETACH DELETE x;") graph.query("MATCH (x:Global:RelationInstance) DETACH DELETE x;") create_roles() create_topics() create_actions() create_terms() create_parties() create_documents() create_demo_playbook() graph.schema_check()
def delete_by_id(cls, rel_id): ret = graph.query(''' MATCH (x:RelationInstance)-[:instance_of]->(xcls:RelationClass) WHERE id(x) = $rel_id OPTIONAL MATCH (x)-[:to]->(to_inst), (x)<-[:from]-(from_inst) DETACH DELETE x RETURN to_inst, id(to_inst) as to_id, xcls.name as relcls_name, from_inst, id(from_inst) as from_id;''', rel_id=rel_id) return ret
def update_properties(cls, rel_id, new_props): query = ''' MATCH (r:RelationInstance) WHERE id(r) = {rel_id} SET r += {new_props} RETURN r; ''' assert rel_id > 0 ret = graph.query(query, rel_id=rel_id, new_props=new_props) return ret
def fetch_by_name(cls, name): # qret = cls._fetch( # match_spec=[ # ['match', '(cls:%s)' % cls._type, 'cls.name = {name}'], # ['optional match', '(cls)-[:isa]->(supercls:%s)' % cls._type, None]], # params={'name': name}) # TODO: fix this to use the schema better and work for other fetch_* methods as well. qret = graph.query(""" MATCH (cls:Class {name: $clsname}) OPTIONAL MATCH isa=(cls)-[:isa*1..10]->(_supercls:Class {name: "Any"}) WITH cls, isa, extract(n IN nodes(isa) | n.scope) AS thing WITH cls, isa, filter(x IN thing WHERE size(x) > 0) AS clean RETURN cls, id(cls) as cls_id, labels(cls) as labels, nodes(isa)[1] as supercls, [isa_n in nodes(isa) where exists(isa_n.fields) | isa_n.fields] as isa_fields, coalesce(head(clean), []) as isa_scope; """, clsname=name) if len(qret) == 0: return None print "=================qurrr===", qret # if len(qret[0]) > 1: # raise ValueError('%s.fetch_by_name returned more than 1 result'%cls._type, qret) row = qret[0] clsdata = copy(dict(row['cls'])) clsdata['_id'] = row['cls_id'] clsdata['_labels'] = row['labels'] clsdata['supercls'] = dict(row['supercls']).get('name') LOG.debug('clsdata=%r' % clsdata) if clsdata.get('fields', None) is not None: #print 'fields=%r' % clsdata['fields'] try: fieldata = json.loads(clsdata['fields']) except: fieldata = None if not fieldata: # walk the isa hierarchy and look for field defs for parent_fieldspec in row['isa_fields'] or []: if parent_fieldspec and json.loads(parent_fieldspec): clsdata['fields'] = parent_fieldspec break LOG.debug('loading %r' % clsdata) obj = cls.get_schema().load(clsdata) if obj.errors: raise ValueError('error objectifying', obj.errors) return obj.data
def destroy_and_refixture(): LOG.debug('destroy_and_refixture()') #graph.db_handle().delete_all() recreate_constraints() LOG.debug(graph.query('match (n) return count(distinct n)')) create_classes() create_relationships() # LOG.debug('classes#={!r}'.format(graph.query('match (c:Class) return count(distinct c)'))) # LOG.debug('relationclasses#={!r}'.format(graph.query('match (rc:RelationClass) return count(distinct rc)'))) graph.dump_info() graph.schema_check()
def update_properties(cls, inst_id, new_props): assert inst_id is not None assert inst_id > 0 assert '_oid' not in new_props # don't allow changing IDs of things ret = graph.query(''' MATCH (x:Instance) WHERE id(x) = $inst_id SET x += $new_props RETURN x; ''', inst_id=inst_id, new_props=new_props) return ret
def create(self, _global=False): if self.supercls is not None: create_query = """ MATCH (supercls:`%s` { name: $supername }), (domcls:Class { name: $domname }), (rangecls:Class { name: $rangename }) MERGE (relcls:Thing:`%s` { name: $clsname })-[:isa]->(supercls) SET relcls += $props MERGE (relcls)-[:domain]->(domcls) MERGE (relcls)-[:range]->(rangecls) WITH relcls CALL apoc.create.addLabels(relcls, $cls_labels) YIELD node AS n_rel RETURN id(n_rel) as relcls_id; """ % (self._type, self._type) else: create_query = """ MATCH (domcls:Class { name: $domname }), (rangecls:Class { name: $rangename }) MERGE (relcls:Thing:`%s` { name: $clsname }) SET relcls += $props MERGE (relcls)-[:domain]->(domcls) MERGE (relcls)-[:range]->(rangecls) WITH relcls CALL apoc.create.addLabels(relcls, $cls_labels) YIELD node AS n_rel RETURN id(n_rel) as relcls_id; """ % self._type #print 'query=%s' % create_query obj_props = self._get_props() obj_labels = [self.name] is_global = _global or self._global if is_global: obj_labels.append('Global') assert obj_props['_oid'] is not None else: obj_labels.append('Local') obj_props.setdefault('_oid', str(uuid.uuid4())) qret = graph.query(create_query, supername=self.supercls, cls_labels=obj_labels, clsname=self.name, domname=self.domain, rangename=self.range, props=self._get_props()) #assert len(qret) == 1 self._id = qret[0]['relcls_id'] return qret
def recreate_constraints(ns_suffix=''): LOG.debug('recreate_constraints()') cons = graph.get_constraints() LOG.debug('constraints={!r}'.format(cons)) for c in cons: drop_query = 'DROP %s' % c ret = graph.query(drop_query) cons2 = graph.get_constraints() graph.add_unique_constraint('Thing%s' % ns_suffix, '_oid') graph.add_unique_constraint('Class', 'name') graph.add_unique_constraint('RelationClass', 'name') cons3 = graph.get_constraints() new_cons = list(set(cons3) - set(cons)) if len(new_cons): LOG.debug("New constraints: {!r}".format(new_cons))
def fetch_by_id(cls, inst_id): ret = graph.query(""" MATCH (x:Instance)-[:instance_of]->(cx:Class) WHERE id(x) = $inst_id RETURN x, cx, id(x) as x_id LIMIT 1; """, inst_id=inst_id) # TODO: parse/objectify this with a schema if len(ret): raw_obj = ret[0]['x'] obj = Instance(class_name=dict(ret[0]['cx'])['name'], **dict(raw_obj)) #obj.class_name = dict(ret[0]['cx'])['name'] obj._id = ret[0]['x_id'] return obj else: LOG.debug('no Instance found for id: ', inst_id) return None
def create(self, _global=False): if self.supercls is not None: create_query = """ MATCH (supercls:%s {name: $supername}) MERGE (cls:Thing:`%s` {name: $clsname}) SET cls += $props MERGE (cls)-[:isa]->(supercls) WITH cls CALL apoc.create.addLabels(cls, $clslabels) YIELD node AS n_cls RETURN id(n_cls) as cls_id; """ % (self._type, self._type) else: create_query = """ MERGE (cls:Thing:`%s` {name: $clsname}) SET cls += $props WITH cls CALL apoc.create.addLabels(cls, $clslabels) YIELD node AS n_cls RETURN id(n_cls) as cls_id; """ % self._type obj_props = self._get_props() obj_labels = [self.name] is_global = _global or self._global print "is---->", is_global if is_global: obj_labels.append('Global') assert obj_props['_oid'] is not None else: obj_labels.append('Local') obj_props.setdefault('_oid', str(uuid.uuid4())) qret = graph.query(create_query, supername=self.supercls, clslabels=obj_labels, clsname=self.name, props=self._get_props()) #assert len(qret) == 1 self._id = qret[0]['cls_id'] return qret
def fetch_by_id(cls, relinst_id): ret = graph.query(""" MATCH (x:RelationInstance)-[:instance_of]->(cx:RelationClass) WHERE id(x) = $rel_id OPTIONAL MATCH (x)<-[:from]-(from:Instance)-[:instance_of]->(fromcls:Class), (x)-[:to]->(to:Instance)-[:instance_of]->(tocls:Class) RETURN x, cx, id(x) as x_id, from, id(from) as from_id, to, id(to) as to_id, fromcls.name as from_cls, tocls.name as to_cls LIMIT 1 """, rel_id=relinst_id) # TODO: parse/objectify this with a schema if len(ret): row = ret[0] rel_obj = copy(dict(row['x'])) rel_obj['class_name'] = dict(row['cx'])['name'] rel_obj['_id'] = row['x_id'] rel_obj['dst'] = {'_id': row['to_id'], 'class': row['to_cls']} rel_obj['src'] = {'_id': row['from_id'], 'class': row['from_cls']} return rel_obj else: print 'no RelationInstance found for id: ', relinst_id return None
def get(self, inst_class=None): if inst_class: return 'class=%s' % inst_class return graph.query( 'match (x:Instance)-[:instance_of]->(c:Class) return id(x) as id, properties(x) as props, c.name as class;' ), 200
def destroy_instances(): graph.query("MATCH (x:Instance) DETACH DELETE x;") graph.query("MATCH (x:RelationInstance) DETACH DELETE x;")