def clear(self): """Clear all nodes and relationships from the graph (except reference node). """ ref_node = self.get_reference_node() cypher.execute(self, "START n=node(*) " "MATCH n-[r?]-() " "WHERE ID(n) <> {Z} " "DELETE n, r", { "Z": ref_node._id })
def is_related_to(self, other, direction=Direction.BOTH, type=None): """ Return :py:const:`True` if the current node is related to the other node using the relationship criteria supplied, :py:const:`False` otherwise. """ if not isinstance(other, Node): raise ValueError if direction == Direction.BOTH: query = "start a=node({}),b=node({}) where a-{}-b return count(*)" elif direction == Direction.OUTGOING: query = "start a=node({}),b=node({}) where a-{}->b return count(*)" elif direction == Direction.INCOMING: query = "start a=node({}),b=node({}) where a<-{}-b return count(*)" else: raise ValueError if type: type = "[:" + type + "]" else: type = "" type = type or "" query = query.format(self.get_id(), other.get_id(), type) graphdb = self._spawn(GraphDatabaseService, self._uri.rpartition("/node")[0] + "/") rows, columns = cypher.execute(query, graphdb) return bool(rows)
def get_relationship_count(self): """Fetch the number of relationships in this graph as an integer. """ data, metadata = cypher.execute(self, "start z=rel(*) return count(z)") if data and data[0]: return data[0][0] else: return 0
def get_node_count(self): """Fetch the number of nodes in this graph as an integer. """ data, metadata = cypher.execute(self, "start z=node(*) return count(z)") if data and data[0]: return data[0][0] else: return 0
def get_relationships_with(self, other, direction=Direction.BOTH, *types): """Return all relationships between this node and another node using the relationship criteria supplied. """ if not isinstance(other, Node): raise ValueError if direction == Direction.BOTH: query = "start a=node({0}),b=node({1}) match a-{2}-b return r" elif direction == Direction.OUTGOING: query = "start a=node({0}),b=node({1}) match a-{2}->b return r" elif direction == Direction.INCOMING: query = "start a=node({0}),b=node({1}) match a<-{2}-b return r" else: raise ValueError if types: type = "[r:" + "|".join("`" + type + "`" for type in types) + "]" else: type = "[r]" query = query.format(self.id, other.id, type) data, metadata = cypher.execute(self._graph_db, query) return [row[0] for row in data]
def get_or_create_relationships(self, *relationships): """Fetch or create relationships with the specified criteria depending on whether or not such relationships exist. Each relationship descriptor should be a tuple of (start, type, end) or (start, type, end, data) where start and end are either existing :py:class:`Node` instances or :py:const:`None` (both nodes cannot be :py:const:`None`):: # set up three nodes alice, bob, carol = graph_db.create( {"name": "Alice"}, {"name": "Bob"}, {"name": "Carol"} ) # ensure Alice and Bob and related ab = graph_db.relate((alice, "LOVES", bob, {"since": 2006})) # ensure relationships exist between Alice, Bob and Carol # creating new relationships only where necessary rels = graph_db.relate( (alice, "LOVES", bob), (bob, "LIKES", alice), (carol, "LOVES", bob), (alice, "HATES", carol), ) # ensure Alice has an outgoing LIKES relationship # (a new node will be created if required) friendship = graph_db.relate((alice, "LIKES", None)) # ensure Alice has an incoming LIKES relationship # (a new node will be created if required) friendship = graph_db.relate((None, "LIKES", alice)) Uses Cypher `CREATE UNIQUE` clause, raising :py:class:`NotImplementedError` if server support not available. """ start, relate, return_, params = [], [], [], {} for i, rel in enumerate(relationships): try: start_node, type, end_node = rel[0:3] except IndexError: raise ValueError(rel) type = "`" + type + "`" if len(rel) > 3: param = "D" + str(i) type += " {" + param + "}" params[param] = rel[3] if start_node: start.append("a{0}=node({1})".format(i, start_node.id)) if end_node: start.append("b{0}=node({1})".format(i, end_node.id)) if start_node and end_node: relate.append("a{0}-[r{0}:{1}]->b{0}".format(i, type)) elif start_node: relate.append("a{0}-[r{0}:{1}]->()".format(i, type)) elif end_node: relate.append("()-[r{0}:{1}]->b{0}".format(i, type)) else: raise ValueError("Neither start node nor end node specified " \ "in relationship {0}: {1} ".format(i, rel)) return_.append("r{0}".format(i)) query = "START {0} CREATE UNIQUE {1} RETURN {2}".format( ",".join(start), ",".join(relate), ",".join(return_) ) try: data, metadata = cypher.execute(self, query, params) return data[0] except cypher.CypherError: raise NotImplementedError( "The Neo4j server at <{0}> does not support " \ "Cypher CREATE UNIQUE clauses or the query contains " \ "an unsupported property type".format(self._uri) )