def dump_separated_values(self, cursor, separator, header): if header: self.console.write_metadata( separator.join( cypher_repr(key, quote=u'"') for key in cursor.keys())) for record in cursor: self.console.write( separator.join( cypher_repr(value, quote=u'"') for value in record.values()))
def _unwind_merge_query(data, merge_key, labels=None, keys=None, return_expr=None): pl = merge_key[0] pk = merge_key[1:] if keys: # data is list of lists indexes = [keys.index(key) for key in pk] fields = [Literal("r[%d]" % i) for i in range(len(keys))] set_rhs = cypher_repr(dict(zip(keys, fields))) else: # data is list of dicts indexes = list(pk) set_rhs = "r" merge_key_string = ", ".join("{}:r[$ix[{}]]".format(cypher_escape(key), i) for i, key in enumerate(pk)) merge_pattern = "(_:%s {%s})" % (cypher_escape(pl), merge_key_string) cypher = ("UNWIND $data AS r " "MERGE %s " "SET _%s " "SET _ = %s " % (merge_pattern, _label_string(pl, *(labels or ())), set_rhs)) if return_expr: cypher += " RETURN %s" % return_expr return cypher, {"data": data, "ix": indexes}
def merge_nodes(tx, data, primary_label, primary_key, labels=None, keys=None): """ Merge nodes from an iterable sequence of raw node data. :param tx: :param data: list of properties :param primary_label: :param primary_key: :param labels: :param keys: :returns: """ if keys: # data is list of lists primary_index = keys.index(primary_key) fields = [Literal("r[%d]" % i) for i in range(len(keys))] set_rhs = cypher_repr(dict(zip(keys, fields))) else: # data is list of dicts primary_index = primary_key set_rhs = "r" cypher = ("UNWIND $data AS r " "MERGE (_:%s {%s:r[$key]}) " "SET _%s " "SET _ = %s " "RETURN id(_)" % (cypher_escape(primary_label), cypher_escape(primary_key), _label_string(labels, primary_label), set_rhs)) for record in tx.run(cypher, data=data, key=primary_index): yield record[0]
def get(self, identity): """ Create a new :class:`.RelationshipMatch` that filters by identity and returns the first matched :class:`.Relationship`. This can be used to match and return a :class:`.Relationship` by ID. >>> relationships.get(1234) Relationship(...) If no such :class:`.Relationship` is found, :py:const:`None` is returned instead. Contrast with `matcher[1234]` which raises a :py:exc:`KeyError` if no entity is found. """ t = type(identity) if issubclass(t, (list, tuple, set, frozenset)): missing = [ i for i in identity if i not in self.graph.relationship_cache ] if missing: list(self.match().where("id(_) in %s" % cypher_repr(missing))) return t(self.graph.relationship_cache.get(i) for i in identity) else: try: return self.graph.relationship_cache[identity] except KeyError: return self.match().where("id(_) = %d" % identity).first()
def _set_properties_clause(value, keys): if keys is None: # data is list of dicts return "SET _ = %s" % value else: # data is list of lists fields = [CypherExpression("%s[%d]" % (value, i)) for i in range(len(keys))] return "SET _ = " + cypher_repr(OrderedDict(zip(keys, fields)))
def _on_create_set_properties_clause(expr, all_keys, keys): if keys is None: return None else: # data is list of lists d = OrderedDict() for i, key in enumerate(all_keys): if key in keys: d[key] = CypherExpression("%s[%d]" % (expr, i)) return "ON CREATE SET _ += " + cypher_repr(d)
def write_value(value, **styles): if value is None: return if isinstance(value, string_types): value = ustr(value) if any(ch in value for ch in quotable): value = quote + value.replace(quote, escaped_quote) + quote else: value = cypher_repr(value) secho(value, file, nl=False, **styles)
def data_row(values): for value in values: if value is None: yield "" continue if isinstance(value, string_types): value = ustr(value) if any(ch in value for ch in quotable): value = quote + value.replace(quote, escaped_quote) + quote else: value = cypher_repr(value) yield value
def _merge_clause(value, merge_key, keys, prefix, suffix): pl, pk = _unpack_merge_key(merge_key) if keys is None: ix = list(pk) else: ix = [keys.index(key) for key in pk] merge_key_string = ", ".join("%s:%s[%s]" % (cypher_escape(key), value, cypher_repr(ix[i])) for i, key in enumerate(pk)) if merge_key_string: return "MERGE %s_:%s {%s}%s" % (prefix, cypher_escape(pl), merge_key_string, suffix) else: return "MERGE %s_:%s%s" % (prefix, cypher_escape(pl), suffix)
def _set_properties_clause(expr, keys, exclude_keys=()): if keys is None: # data is list of dicts return "SET _ += %s" % expr else: # data is list of lists d = OrderedDict() for i, key in enumerate(keys): if exclude_keys and key in exclude_keys: continue d[key] = CypherExpression("%s[%d]" % (expr, i)) return "SET _ += " + cypher_repr(d)
def __repr__(self): from py2neo.cypher import cypher_repr if self.__selected: properties = { key: self.__items[key] for key in self.__selected if key in self.__items } else: properties = { key: self.__items[key] for key in sorted(self.__items) } return cypher_repr(properties, **self.__kwargs)
def _unwind_create_query(data, labels=None, keys=None, return_expr=None): if keys: # data is list of lists fields = [Literal("r[%d]" % i) for i in range(len(keys))] set_rhs = cypher_repr(dict(zip(keys, fields))) else: # data is list of dicts set_rhs = "r" cypher = ("UNWIND $data AS r " "CREATE (_%s) " "SET _ = %s" % (_label_string(*labels), set_rhs)) if return_expr: cypher += " RETURN %s" % return_expr return cypher, {"data": list(data)}
def get(self, identity): """ Create a new :class:`.NodeMatch` that filters by identity and returns the first matched :class:`.Node`. This can be used to match and return a :class:`.Node` by ID. >>> matches.get(1234) Node('Person', name='Alice') If no such :class:`.Node` is found, :py:const:`None` is returned instead. Contrast with ``matcher[1234]`` which raises a :py:exc:`KeyError` if no entity is found. """ t = type(identity) if issubclass(t, (list, tuple, set, frozenset)): matches = self.match().where("id(_) in %s" % cypher_repr(list(identity))) return t(matches) else: return self.match().where("id(_) = %d" % identity).first()
def create_nodes(tx, data, labels=None, keys=None): """ Create nodes from an iterable sequence of raw node data. :param tx: :param data: :param labels: :param keys: :returns: """ if keys: # data is list of lists fields = [Literal("r[%d]" % i) for i in range(len(keys))] set_rhs = cypher_repr(dict(zip(keys, fields))) else: # data is list of dicts set_rhs = "r" cypher = ("UNWIND $data AS r " "CREATE (_%s) " "SET _ = %s " "RETURN id(_)" % (_label_string(labels), set_rhs)) for record in tx.run(cypher, data=list(data)): yield record[0]
def test_empty(self): a = Node() r = cypher_repr(a) self.assertEqual("({})", r)
def key_value_string(self, value, ix): return ", ".join("%s:%s[%s]" % (cypher_escape(key), value, cypher_repr(ix[i])) for i, key in enumerate(self.__pk))
def __repr__(self): from py2neo.compat import unicode_repr from py2neo.cypher import cypher_repr return unicode_repr(cypher_repr(self))
def test_duration_property(self): a = Node(dur=Duration(days=3)) r = cypher_repr(a) self.assertEqual("({dur: duration('P3D')})", r)
def test_datetime_property(self): a = Node(dt=DateTime(1970, 1, 1, 12, 34, 56)) r = cypher_repr(a) self.assertEqual("({dt: datetime('1970-01-01T12:34:56.000000000')})", r)
def test_time_property(self): a = Node(t=Time(12, 34, 56)) r = cypher_repr(a) self.assertEqual("({t: time('12:34:56.000000000')})", r)
def test_date_property(self): a = Node(d=Date(1970, 1, 1)) r = cypher_repr(a) self.assertEqual("({d: date('1970-01-01')})", r)
def __db_merge__(self, tx, primary_label=None, primary_key=None): from py2neo.cypher import cypher_escape, cypher_repr nodes = list(self.nodes()) match_clauses = [] merge_clauses = [] parameters = {} returns = {} for i, node in enumerate(nodes): node_id = "a%d" % i param_id = "x%d" % i remote_node = remote(node) if remote_node: match_clauses.append("MATCH (%s) WHERE id(%s)={%s}" % (node_id, node_id, param_id)) parameters[param_id] = remote_node._id else: merge_label = getattr(node, "__primarylabel__", None) or primary_label if merge_label is None: label_string = "".join(":" + cypher_escape(label) for label in sorted(node.labels())) elif node.labels(): label_string = ":" + cypher_escape(merge_label) else: label_string = "" merge_keys = getattr(node, "__primarykey__", None) or primary_key if merge_keys is None: merge_keys = () elif is_collection(merge_keys): merge_keys = tuple(merge_keys) else: merge_keys = (merge_keys, ) if merge_keys: property_map_string = cypher_repr({ k: v for k, v in dict(node).items() if k in merge_keys }) else: property_map_string = cypher_repr(dict(node)) merge_clauses.append( "MERGE (%s%s %s)" % (node_id, label_string, property_map_string)) if node.labels(): merge_clauses.append( "SET %s%s" % (node_id, "".join(":" + cypher_escape(label) for label in sorted(node.labels())))) if merge_keys: merge_clauses.append("SET %s={%s}" % (node_id, param_id)) parameters[param_id] = dict(node) node._set_remote_pending(tx) returns[node_id] = node clauses = match_clauses + merge_clauses for i, relationship in enumerate(self.relationships()): if not remote(relationship): rel_id = "r%d" % i start_node_id = "a%d" % nodes.index(relationship.start_node()) end_node_id = "a%d" % nodes.index(relationship.end_node()) type_string = cypher_escape(relationship.type()) param_id = "y%d" % i clauses.append("MERGE (%s)-[%s:%s]->(%s) SET %s={%s}" % (start_node_id, rel_id, type_string, end_node_id, rel_id, param_id)) parameters[param_id] = dict(relationship) returns[rel_id] = relationship relationship._set_remote_pending(tx) statement = "\n".join(clauses + ["RETURN %s LIMIT 1" % ", ".join(returns)]) tx.entities.append(returns) list(tx.run(statement, parameters))
def cyphify(obj, ensure_ascii=True): return cypher_repr(obj)
def test_single_property(self): a = Node(name="Alice") r = cypher_repr(a) self.assertEqual("({name: 'Alice'})", r)
def test_property_and_label(self): a = Node("Person", name="Alice") r = cypher_repr(a) self.assertEqual("(:Person {name: 'Alice'})", r)
def __str__(self): return xstr(cypher_repr(self))
def load_locations_to_kg(): graph = Graph(uri=conf_dict['neo4j_address'], auth=(conf_dict['neo4j_user'], conf_dict['neo4j_pass'])) for label in ("Location", "ProvinceName", "CityName", "AreaName"): graph.run("CREATE INDEX ON :%s(name)" % label) areaCode, provinceCode, cityCode = {}, {}, {} pendingToLink = [] with open("dump_locations.json", "r", encoding="utf8") as dumpFile: while True: newLine = dumpFile.readline() if not newLine: break # if "洪山" in newLine :print("read") entity = json.loads(newLine) # print(entity['type']) if entity['type'] == "ProvinceName": provinceCode[entity['code']] = entity['name'] elif entity['type'] == "CityName": cityCode[entity['code']] = entity['name'] elif entity['type'] == "AreaName": areaCode[entity['code']] = entity['name'] this = {} this['type'] = entity['type'] this['name'] = entity['name'] if "areaCode" in entity: this["areaCode"] = entity['areaCode'] if "cityCode" in entity: this["cityCode"] = entity['cityCode'] if "provinceCode" in entity: this["provinceCode"] = entity['provinceCode'] pendingToLink.append(this) # if "洪山" in this['name']:print("graph") try: graph.run( "MERGE (:Location:%s{_subgraph:'baike',%s});" % (entity['type'], ",".join( map( lambda k: "%s:%s" % (make_neo4j_key(k), cypher_repr(";".join(entity[k]) if isinstance( entity[k], list) else entity[k])), (k for k in entity if k != "type"))))) except Exception as e: print( repr( "MERGE (:Location:%s{_subgraph:'baike',%s});" % (entity['type'], ",".join( map( lambda k: "%s:%s" % (make_neo4j_key(k), cypher_repr(";".join(entity[k]) if isinstance( entity[k], list) else entity[k])), (k for k in entity if k != "type")))))) exit(-1) for this in pendingToLink: if "areaCode" in this: try: areaName = areaCode[this['areaCode']] except KeyError: pass else: graph.run( "MATCH (a:Location),(b:AreaName) WHERE a.name='%s' AND b.name='%s' MERGE (a)-[:位于]->(b)" % (this['name'], areaName)) elif "cityCode" in this: try: cityName = cityCode[this['cityCode']] except KeyError: pass else: graph.run( "MATCH (a:Location),(b:CityName) WHERE a.name='%s' AND b.name='%s' MERGE (a)-[:位于]->(b)" % (this['name'], cityName)) elif "provinceCode" in this: try: provinceName = provinceCode[this['provinceCode']] except KeyError: pass else: graph.run( "MATCH (a:Location),(b:ProvinceName) WHERE a.name='%s' AND b.name='%s' MERGE (a)-[:位于]->(b)" % (this['name'], provinceName))