Пример #1
0
 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
     })
Пример #2
0
 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)
Пример #3
0
 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
Пример #4
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
Пример #5
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]
Пример #6
0
    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)
            )