Beispiel #1
0
 def apply(x):
     if isinstance(x, dict):
         inst.update(x)
     elif is_collection(x):
         for item in x:
             apply(item)
     elif isinstance(x, string_types):
         inst.add_label(ustr(x))
     else:
         raise TypeError("Cannot cast %s to Node" %
                         obj.__class__.__name__)
Beispiel #2
0
 def hydrate_(data, inst=None):
     if isinstance(data, dict):
         if "self" in data:
             if "type" in data:
                 data["start"] = uri_to_id(data["start"])
                 data["end"] = uri_to_id(data["end"])
                 return hydrate_relationship(graph,
                                             uri_to_id(data["self"]),
                                             inst=inst,
                                             **data)
             else:
                 return hydrate_node(graph,
                                     uri_to_id(data["self"]),
                                     inst=inst,
                                     **data)
         elif "nodes" in data and "relationships" in data:
             data["nodes"] = list(map(uri_to_id, data["nodes"]))
             data["relationships"] = list(
                 map(uri_to_id, data["relationships"]))
             if "directions" not in data:
                 directions = []
                 relationships = graph.evaluate(
                     "MATCH ()-[r]->() WHERE id(r) IN {x} RETURN collect(r)",
                     x=data["relationships"])
                 for i, relationship in enumerate(relationships):
                     if relationship.start_node.identity == data[
                             "nodes"][i]:
                         directions.append("->")
                     else:
                         directions.append("<-")
                 data["directions"] = directions
             return hydrate_path(graph, data)
         else:
             # from warnings import warn
             # warn("Map literals returned over the Neo4j REST interface are ambiguous "
             #      "and may be hydrated as graph objects")
             return data
     elif is_collection(data):
         return type(data)(map(hydrate_, data))
     else:
         return data
    def _query_and_parameters(self, count=False):
        """ A tuple of the Cypher query and parameters used to select
        the relationships that match the criteria for this selection.

        :return: Cypher query string
        """
        def verify_node(n):
            if n.graph != self.graph:
                raise ValueError("Node %r does not belong to this graph" % n)
            if n.identity is None:
                raise ValueError("Node %r is not bound to a graph" % n)

        def r_type_name(r):
            try:
                return r.__name__
            except AttributeError:
                return r

        clauses = []
        parameters = {}
        if self._r_type is None:
            relationship_detail = ""
        elif is_collection(self._r_type):
            relationship_detail = ":" + "|:".join(
                cypher_escape(r_type_name(t)) for t in self._r_type)
        else:
            relationship_detail = ":%s" % cypher_escape(
                r_type_name(self._r_type))
        if not self._nodes:
            clauses.append("MATCH (a)-[_" + relationship_detail + "]->(b)")
        elif isinstance(self._nodes, Sequence):
            if len(self._nodes) >= 1 and self._nodes[0] is not None:
                start_node = Node.cast(self._nodes[0])
                verify_node(start_node)
                clauses.append("MATCH (a) WHERE id(a) = {x}")
                parameters["x"] = start_node.identity
            if len(self._nodes) >= 2 and self._nodes[1] is not None:
                end_node = Node.cast(self._nodes[1])
                verify_node(end_node)
                clauses.append("MATCH (b) WHERE id(b) = {y}")
                parameters["y"] = end_node.identity
            if len(self._nodes) >= 3:
                raise ValueError("Node sequence cannot be longer than two")
            clauses.append("MATCH (a)-[_" + relationship_detail + "]->(b)")
        elif isinstance(self._nodes, Set):
            nodes = {node for node in self._nodes if node is not None}
            if len(nodes) >= 1:
                start_node = Node.cast(nodes.pop())
                verify_node(start_node)
                clauses.append("MATCH (a) WHERE id(a) = {x}")
                parameters["x"] = start_node.identity
            if len(nodes) >= 1:
                end_node = Node.cast(nodes.pop())
                verify_node(end_node)
                clauses.append("MATCH (b) WHERE id(b) = {y}")
                parameters["y"] = end_node.identity
            if len(nodes) >= 1:
                raise ValueError("Node set cannot be larger than two")
            clauses.append("MATCH (a)-[_" + relationship_detail + "]-(b)")
        else:
            raise ValueError("Nodes must be passed as a Sequence or a Set")
        if self._conditions:
            conditions = []
            for condition in self._conditions:
                if isinstance(condition, tuple):
                    condition, param = condition
                    parameters.update(param)
                conditions.append(condition)
            clauses.append("WHERE %s" % " AND ".join(conditions))
        if count:
            clauses.append("RETURN count(_)")
        else:
            clauses.append("RETURN _")
            if self._order_by:
                clauses.append("ORDER BY %s" % (", ".join(self._order_by)))
            if self._skip:
                clauses.append("SKIP %d" % self._skip)
            if self._limit is not None:
                clauses.append("LIMIT %d" % self._limit)
        return " ".join(clauses), parameters