def test_list_data(self, rel_data_lists, rel_type, rel_keys): q, p = unwind_create_relationships_query(rel_data_lists, rel_type, keys=rel_keys) assert q == ("UNWIND $data AS r\n" "MATCH (a) WHERE id(a) = r[0]\n" "MATCH (b) WHERE id(b) = r[2]\n" "CREATE (a)-[_:WORKS_FOR]->(b)\n" "SET _ += {`employee id`: r[1][0], `job title`: r[1][1], since: r[1][2]}") assert p == {"data": rel_data_lists}
def test_dict_data(self, rel_data_dicts, rel_type): q, p = unwind_create_relationships_query(rel_data_dicts, rel_type) assert q == ("UNWIND $data AS r\n" "MATCH (a) WHERE id(a) = r[0]\n" "MATCH (b) WHERE id(b) = r[2]\n" "CREATE (a)-[_:WORKS_FOR]->(b)\n" "SET _ += r[1]") assert p == {"data": rel_data_dicts}
def test_with_end_node_key(self, rel_data_dicts, rel_type, end_node_key): q, p = unwind_create_relationships_query(rel_data_dicts, rel_type, end_node_key=end_node_key) assert q == ("UNWIND $data AS r\n" "MATCH (a) WHERE id(a) = r[0]\n" "MATCH (b:Company {name:r[2]})\n" "CREATE (a)-[_:WORKS_FOR]->(b)\n" "SET _ += r[1]") assert p == {"data": rel_data_dicts}
def test_with_start_node_no_keys(self, rel_data_lists_no_key, rel_type, rel_keys, start_node_key): q, p = unwind_create_relationships_query(rel_data_lists_no_key, rel_type, start_node_key=start_node_key, end_node_key="Company", keys=rel_keys) assert q == ("UNWIND $data AS r\n" "MATCH (a:Person {name:r[0]})\n" "MATCH (b:Company)\n" "CREATE (a)-[_:WORKS_FOR]->(b)\n" "SET _ += {`employee id`: r[1][0], `job title`: r[1][1], since: r[1][2]}") assert p == {"data": rel_data_lists_no_key}
def test_with_start_node_double_key(self, rel_data_lists_double_key, rel_keys, rel_type, start_node_double_key): q, p = unwind_create_relationships_query(rel_data_lists_double_key, rel_type, start_node_key=start_node_double_key, keys=rel_keys) assert q == ("UNWIND $data AS r\n" "MATCH (a:Person {name:r[0][0], `family name`:r[0][1]})\n" "MATCH (b) WHERE id(b) = r[2]\n" "CREATE (a)-[_:WORKS_FOR]->(b)\n" "SET _ += {`employee id`: r[1][0], `job title`: r[1][1], since: r[1][2]}") assert p == {"data": rel_data_lists_double_key}
def test_with_start_node_key(self, rel_data_dicts, rel_type, start_node_key): q, p = unwind_create_relationships_query(rel_data_dicts, rel_type, start_node_key=start_node_key) assert q == ("UNWIND $data AS r\n" "MATCH (a:Person {name:r[0]})\n" "MATCH (b) WHERE id(b) = r[2]\n" "CREATE (a)-[_:WORKS_FOR]->(b)\n" "SET _ = r[1]") assert p == {"data": rel_data_dicts}
def merge_relationships(tx, data, merge_key, keys=None, start_node_key=None, end_node_key=None): """ Merge relationships from an iterable sequence of raw relationship data. :param tx: :class:`.Transaction` in which to carry out this operation :param data: :param merge_key: :param keys: :param start_node_key: :param end_node_key: :return: """ list( tx.run(*unwind_create_relationships_query( data, merge_key, keys, start_node_key, end_node_key)))
def create_relationships(tx, data, rel_type, start_node_key=None, end_node_key=None, keys=None): """ Create relationships from an iterable sequence of raw relationship data. The raw relationship `data` is supplied as a list of triples (or 3-item lists), each representing (start_node, detail, end_node). The `rel_type` specifies the type of relationship to create, and is fixed for the entire data set. Start and end node information can either be provided as an internal node ID or, in conjunction with a `start_node_key` or `end_node_key`, a tuple or list of property values to ``MATCH``. For example, to link people to their place of work, the code below could be used: >>> from py2neo import Graph >>> from py2neo.bulk import create_relationships >>> g = Graph() >>> data = [ (("Alice", "Smith"), {"since": 1999}, "ACME"), (("Bob", "Jones"), {"since": 2002}, "Bob Corp"), (("Carol", "Singer"), {"since": 1981}, "The Daily Planet"), ] >>> create_relationships(g.auto(), data, "WORKS_FOR", \\ start_node_key=("Person", "name", "family name"), end_node_key=("Company", "name")) If the company node IDs were already known by other means, the code could instead look like this: >>> data = [ (("Alice", "Smith"), {"since": 1999}, 123), (("Bob", "Jones"), {"since": 2002}, 124), (("Carol", "Singer"), {"since": 1981}, 201), ] >>> create_relationships(g.auto(), data, "WORKS_FOR", \\ start_node_key=("Person", "name", "family name")) These `start_node_key` and `end_node_key` arguments are interpreted in a similar way to the `merge_key` of :func:`merge_nodes`, except that the values are instead used to construct ``MATCH`` patterns. Additionally, passing :py:const:`None` indicates that a match by node ID should be used. The table below shows example combinations, where ``x`` is the input value drawn from the source data. .. table:: :widths: 40 60 ================================================= =========================================================== Argument ``MATCH`` Clause ================================================= =========================================================== :py:const:`None` ``MATCH (a) WHERE id(a) = x`` ``("Person", "name")`` ``MATCH (a:Person {name:x})`` ``("Person", "name", "family name")`` ``MATCH (a:Person {name:x[0], `family name`:x[1]})`` ``(("Person", "Female"), "name")`` ``MATCH (a:Female:Person {name:x})`` ``(("Person", "Female"), "name", "family name")`` ``MATCH (a:Female:Person {name:x[0], `family name`:x[1]})`` ================================================= =========================================================== As with other methods, such as :func:`.create_nodes`, the relationship `data` can also be supplied as a list of property values, indexed by `keys`. This can avoid sending duplicated key names over the network, and alters the method call as follows: >>> data = [ (("Alice", "Smith"), [1999], 123), (("Bob", "Jones"), [2002], 124), (("Carol", "Singer"), [1981], 201), ] >>> create_relationships(g.auto(), data, "WORKS_FOR" \\ start_node_key=("Person", "name", "family name")), keys=["since"]) :param tx: :class:`.Transaction` in which to carry out this operation :param data: relationship data supplied as a list of triples of `(start_node, detail, end_node)` :param rel_type: relationship type name to create :param start_node_key: optional tuple of (label, key1, key2...) on which to match relationship start nodes, matching by node ID if not provided :param end_node_key: optional tuple of (label, key1, key2...) on which to match relationship end nodes, matching by node ID if not provided :param keys: optional set of field names for the relationship `detail` (if supplied as value lists) :return: """ list( tx.run(*unwind_create_relationships_query( data, rel_type, start_node_key, end_node_key, keys)))
def create_relationships(tx, data, rel_type, keys=None, start_node_key=None, end_node_key=None): """ Create relationships from an iterable sequence of raw relationship data. The raw relationship `data` is supplied as a list of triples (or 3-item lists), each representing (start_node, detail, end_node). The `rel_type` specifies the type of relationship to create, and is fixed for the entire data set. Start and end node information can either be provided as an internal node ID or, in conjunction with a `start_node_key` or `end_node_key`, a tuple or list of property values to ``MATCH``. For example, to link people to their place of work, the code below could be used: >>> from py2neo import Graph >>> from py2neo.data.operations import create_relationships >>> g = Graph() >>> data = [ (("Alice", "Smith"), {"since": 1999}, "ACME"), (("Bob", "Jones"), {"since": 2002}, "Bob Corp"), (("Carol", "Singer"), {"since": 1981}, "The Daily Planet"), ] >>> create_relationships(g.auto(), data, "WORKS_FOR", \ start_node_key=("Person", "name", "family name"), \ end_node_key=("Company", "name")) If the company node IDs were already known, the code could instead look like this: >>> data = [ (("Alice", "Smith"), {"since": 1999}, 123), (("Bob", "Jones"), {"since": 2002}, 124), (("Carol", "Singer"), {"since": 1981}, 201), ] >>> create_relationships(g.auto(), data, "WORKS_FOR", \ start_node_key=("Person", "name", "family name")) As with other methods, such as :meth:`.create_nodes`, the relationship `data` can also be supplied as a list of property values, indexed by `keys`. This can avoid sending duplicated key names over the network, and alters the method call as follows: >>> data = [ (("Alice", "Smith"), [1999], 123), (("Bob", "Jones"), [2002], 124), (("Carol", "Singer"), [1981], 201), ] >>> create_relationships(g.auto(), data, "WORKS_FOR", keys=["since"] \ start_node_key=("Person", "name", "family name")) :param tx: :class:`.Transaction` in which to carry out this operation :param data: :param rel_type: :param keys: :param start_node_key: :param end_node_key: :return: """ list( tx.run(*unwind_create_relationships_query( data, rel_type, keys, start_node_key, end_node_key)))