예제 #1
0
 def __init__(self, graph, path):
     self.graph = graph
     dbms_uri = remote(self.graph.graph_service).uri
     self.remote = Remote(dbms_uri.rstrip("/") + path)
     try:
         self.remote.get_json("")
     except GraphError:
         raise NotImplementedError("No extension found at path %r on "
                                   "graph <%s>" %
                                   (path, remote(self.graph).uri))
예제 #2
0
 def __eq__(self, other):
     if not isinstance(other, GraphObject):
         return False
     remote_self = remote(self.__ogm__.node)
     remote_other = remote(other.__ogm__.node)
     if remote_self and remote_other:
         return remote_self == remote_other
     else:
         return self.__primarylabel__ == other.__primarylabel__ and \
                self.__primarykey__ == other.__primarykey__ and \
                self.__primaryvalue__ == other.__primaryvalue__
예제 #3
0
    def match(self, start_node=None, rel_type=None, end_node=None, bidirectional=False, limit=None):
        """ Match and return all relationships with specific criteria.

        For example, to find all of Alice's friends::

            for rel in graph.match(start_node=alice, rel_type="FRIEND"):
                print(rel.end_node()["name"])

        :param start_node: start node of relationships to match (:const:`None` means any node)
        :param rel_type: type of relationships to match (:const:`None` means any type)
        :param end_node: end node of relationships to match (:const:`None` means any node)
        :param bidirectional: :const:`True` if reversed relationships should also be included
        :param limit: maximum number of relationships to match (:const:`None` means unlimited)
        """
        clauses = []
        returns = []
        if start_node is None and end_node is None:
            clauses.append("MATCH (a)")
            parameters = {}
            returns.append("a")
            returns.append("b")
        elif end_node is None:
            clauses.append("MATCH (a) WHERE id(a) = {1}")
            start_node = cast_node(start_node)
            if not remote(start_node):
                raise TypeError("Nodes for relationship match end points must be bound")
            parameters = {"1": remote(start_node)._id}
            returns.append("b")
        elif start_node is None:
            clauses.append("MATCH (b) WHERE id(b) = {2}")
            end_node = cast_node(end_node)
            if not remote(end_node):
                raise TypeError("Nodes for relationship match end points must be bound")
            parameters = {"2": remote(end_node)._id}
            returns.append("a")
        else:
            clauses.append("MATCH (a) WHERE id(a) = {1} MATCH (b) WHERE id(b) = {2}")
            start_node = cast_node(start_node)
            end_node = cast_node(end_node)
            if not remote(start_node) or not remote(end_node):
                raise TypeError("Nodes for relationship match end points must be bound")
            parameters = {"1": remote(start_node)._id, "2": remote(end_node)._id}
        if rel_type is None:
            relationship_detail = ""
        elif is_collection(rel_type):
            relationship_detail = ":" + "|:".join(cypher_escape(t) for t in rel_type)
        else:
            relationship_detail = ":%s" % cypher_escape(rel_type)
        if bidirectional:
            clauses.append("MATCH (a)-[_" + relationship_detail + "]-(b)")
        else:
            clauses.append("MATCH (a)-[_" + relationship_detail + "]->(b)")
        returns.append("_")
        clauses.append("RETURN %s" % ", ".join(returns))
        if limit is not None:
            clauses.append("LIMIT %d" % limit)
        cursor = self.run(" ".join(clauses), parameters)
        while cursor.forward():
            record = cursor.current()
            yield record["_"]
예제 #4
0
파일: json.py 프로젝트: aniket121/asconcept
 def hydrate_(data, inst=None):
     if isinstance(data, dict):
         if "self" in data:
             if "type" in data:
                 return Relationship.hydrate(data["self"], inst=inst, **data)
             else:
                 return Node.hydrate(data["self"], inst=inst, **data)
         elif "nodes" in data and "relationships" in data:
             if "directions" not in data:
                 directions = []
                 relationships = graph.evaluate(
                     "MATCH ()-[r]->() WHERE id(r) IN {x} RETURN collect(r)",
                     x=[int(uri.rpartition("/")[-1]) for uri in data["relationships"]])
                 node_uris = data["nodes"]
                 for i, relationship in enumerate(relationships):
                     if remote(relationship.start_node()).uri == node_uris[i]:
                         directions.append("->")
                     else:
                         directions.append("<-")
                 data["directions"] = directions
             return Path.hydrate(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
예제 #5
0
    def password_change_required(self):
        """ Check if a password change is required for the current user.

        :returns: :const:`True` if a password change is required, :const:`False` otherwise
        """
        status = remote(self).get_json("user/{}".format(self.user))
        return status["password_change_required"]
예제 #6
0
 def _related_objects(self):
     if self.__related_objects is None:
         self.__related_objects = []
         remote_node = remote(self.node)
         if remote_node:
             with remote_node.graph.begin() as tx:
                 self.__db_pull__(tx)
     return self.__related_objects
예제 #7
0
 def __primaryvalue__(self):
     node = self.__ogm__.node
     primary_key = self.__primarykey__
     if primary_key == "__id__":
         remote_node = remote(node)
         return remote_node._id if remote_node else None
     else:
         return node[primary_key]
예제 #8
0
 def __db_push__(self, tx):
     related_objects = self._related_objects
     # 1. merge all nodes (create ones that don't)
     for related_object, _ in related_objects:
         tx.merge(related_object)
     # 2a. remove any relationships not in list of nodes
     subject_id = remote(self.node)._id
     tx.run("MATCH %s WHERE id(a) = {x} AND NOT id(b) IN {y} DELETE _" %
            self.__relationship_pattern,
            x=subject_id,
            y=[remote(obj.__ogm__.node)._id for obj, _ in related_objects])
     # 2b. merge all relationships
     for related_object, properties in related_objects:
         tx.run("MATCH (a) WHERE id(a) = {x} MATCH (b) WHERE id(b) = {y} "
                "MERGE %s SET _ = {z}" % self.__relationship_pattern,
                x=subject_id,
                y=remote(related_object.__ogm__.node)._id,
                z=properties)
예제 #9
0
 def __db_delete__(self, tx):
     ogm = self.__ogm__
     remote_node = remote(ogm.node)
     if remote_node:
         tx.run(
             "MATCH (a) WHERE id(a) = {x} OPTIONAL MATCH (a)-[r]->() DELETE r DELETE a",
             x=remote_node._id)
     for related_objects in ogm.related.values():
         related_objects.clear()
예제 #10
0
 def __db_pull__(self, tx):
     ogm = self.__ogm__
     if not remote(ogm.node):
         selector = GraphObjectSelector(self.__class__, tx.graph)
         selector._selection_class = NodeSelection
         ogm.node = selector.select(self.__primaryvalue__).first()
     tx.pull(ogm.node)
     for related_objects in ogm.related.values():
         related_objects.__db_pull__(tx)
예제 #11
0
 def __db_push__(self, tx):
     ogm = self.__ogm__
     node = ogm.node
     if remote(node):
         tx.push(node)
     else:
         primary_key = getattr(node, "__primarykey__", "__id__")
         if primary_key == "__id__":
             tx.create(node)
         else:
             tx.merge(node)
     for related_objects in ogm.related.values():
         related_objects.__db_push__(tx)
예제 #12
0
    def relationship(self, id_):
        """ Fetch a relationship by ID.

        :param id_:
        """
        entity_uri = "%srelationship/%s" % (remote(self).uri, id_)
        try:
            return Relationship.cache[entity_uri]
        except KeyError:
            relationship = self.evaluate("MATCH ()-[r]->() WHERE id(r)={x} RETURN r", x=id_)
            if relationship is None:
                raise IndexError("Relationship %d not found" % id_)
            else:
                return relationship
예제 #13
0
 def __db_merge__(self, tx, primary_label=None, primary_key=None):
     ogm = self.__ogm__
     node = ogm.node
     if primary_label is None:
         primary_label = getattr(node, "__primarylabel__", None)
     if primary_key is None:
         primary_key = getattr(node, "__primarykey__", "__id__")
     if not remote(node):
         if primary_key == "__id__":
             node.add_label(primary_label)
             tx.create(node)
         else:
             tx.merge(node, primary_label, primary_key)
         for related_objects in ogm.related.values():
             related_objects.__db_push__(tx)
예제 #14
0
 def _bean_dict(self, name):
     info = remote(self).get_json("db/manage/server/jmx/domain/org.neo4j")
     raw_config = [b for b in info["beans"] if b["name"].endswith("name=%s" % name)][0]
     d = {}
     for attribute in raw_config["attributes"]:
         name = attribute["name"]
         value = attribute.get("value")
         if value == "true":
             d[name] = True
         elif value == "false":
             d[name] = False
         else:
             try:
                 d[name] = int(value)
             except (TypeError, ValueError):
                 d[name] = value
     return d
예제 #15
0
    def node(self, id_):
        """ Fetch a node by ID. This method creates an object representing the
        remote node with the ID specified but fetches no data from the server.
        For this reason, there is no guarantee that the entity returned
        actually exists.

        :param id_:
        """
        entity_uri = "%snode/%s" % (remote(self).uri, id_)
        try:
            return Node.cache[entity_uri]
        except KeyError:
            node = self.node_selector.select().where("id(_) = %d" % id_).first()
            if node is None:
                raise IndexError("Node %d not found" % id_)
            else:
                return node
예제 #16
0
 def node_labels(self):
     """ The set of node labels currently defined within the graph.
     """
     return frozenset(remote(self).get_json("labels"))
예제 #17
0
 def __repr__(self):
     return "<%s uri=%r>" % (self.__class__.__name__, remote(self).uri)
예제 #18
0
 def __eq__(self, other):
     try:
         return remote(self) == remote(other)
     except AttributeError:
         return False
예제 #19
0
 def change_password(self, new_password):
     """ Change the password for the current user.
     """
     remote(self).post("user/{}/password".format(self.user), {"password": new_password}, expected=(OK,))
     return new_password
예제 #20
0
 def __repr__(self):
     return "<Graph uri=%r>" % remote(self).uri
예제 #21
0
 def __hash__(self):
     return hash(remote(self).uri)
예제 #22
0
 def __init__(self, graph, ref):
     self.remote_graph = remote(graph)
     self._index_ref = ref + "/index/{label}"
     self._index_key_ref = ref + "/index/{label}/{property_key}"
     self._uniqueness_constraint_ref = ref + "/constraint/{label}/uniqueness"
     self._uniqueness_constraint_key_ref = ref + "/constraint/{label}/uniqueness/{property_key}"
예제 #23
0
 def relationship_types(self):
     """ The set of relationship types currently defined within the graph.
     """
     return frozenset(remote(self).get_json("relationship/types"))
예제 #24
0
 def __contains__(self, entity):
     remote_entity = remote(entity)
     return remote_entity and remote_entity.uri.startswith(remote(self).uri)
예제 #25
0
 def open_browser(self):
     """ Open a page in the default system web browser pointing at
     the Neo4j browser application for this graph.
     """
     webbrowser.open(remote(self.graph_service).uri)
예제 #26
0
 def hydrate_(obj, inst=None):
     # TODO: hydrate directly instead of via HTTP hydration
     if isinstance(obj, Structure):
         signature, args = obj
         if signature == b"N":
             uri = "%snode/%s" % (graph_uri, args[0])
             return Node.hydrate(uri,
                                 inst=inst,
                                 metadata={"labels": list(args[1])},
                                 data=hydrate_(args[2]))
         elif signature == b"R":
             uri = "%srelationship/%s" % (graph_uri, args[0])
             return Relationship.hydrate(
                 uri,
                 inst=inst,
                 start="%snode/%s" % (graph_uri, args[1]),
                 end="%snode/%s" % (graph_uri, args[2]),
                 type=args[3],
                 data=hydrate_(args[4]))
         elif signature == b"P":
             nodes = [hydrate_(node) for node in args[0]]
             u_rels = [
                 UnboundRelationship.hydrate(*map(hydrate_, r))
                 for _, r in args[1]
             ]
             sequence = args[2]
             last_node = nodes[0]
             steps = [last_node]
             for i, rel_index in enumerate(sequence[::2]):
                 next_node = nodes[sequence[2 * i + 1]]
                 last_node_uri = "%snode/%s" % (graph_uri,
                                                remote(last_node)._id)
                 next_node_uri = "%snode/%s" % (graph_uri,
                                                remote(next_node)._id)
                 if rel_index > 0:
                     u_rel = u_rels[rel_index - 1]
                     uri = "%srelationship/%s" % (graph_uri, u_rel.id)
                     rel = Relationship.hydrate(uri,
                                                start=last_node_uri,
                                                end=next_node_uri,
                                                type=u_rel.type,
                                                data=u_rel.properties)
                 else:
                     u_rel = u_rels[-rel_index - 1]
                     uri = "%srelationship/%s" % (graph_uri, u_rel.id)
                     rel = Relationship.hydrate(uri,
                                                start=next_node_uri,
                                                end=last_node_uri,
                                                type=u_rel.type,
                                                data=u_rel.properties)
                 steps.append(rel)
                 steps.append(next_node)
                 last_node = next_node
             return Path(*steps)
         else:
             # If we don't recognise the structure type, just return it as-is
             # TODO: add warning for unsupported structure types
             return obj
     elif isinstance(obj, list):
         return list(map(hydrate_, obj))
     elif isinstance(obj, dict):
         return {key: hydrate_(value) for key, value in obj.items()}
     else:
         return obj