Based on @elyase's answer and source py2neo.Graph.find, I made this code. Please feel free to comment and improve .. :-)
def find_dict(graph, label, key_value=None, limit=None): """ Iterate through a set of labelled nodes, optionally filtering by property key/value dictionary """ if not label: raise ValueError("Empty label") from py2neo.cypher.lang import cypher_escape if key_value is None: statement = "MATCH (n:%s) RETURN n,labels(n)" % cypher_escape(label) else: # quote string values d = {k: "'{}'".format(v) if isinstance(v, str) else v for k, v in key_value.items()} cond = "" for prop, value in d.items(): if not isinstance(value, tuple): value = ('=', value) if cond == "": cond += "n.{prop}{value[0]}{value[1]}".format( prop=prop, value=value, ) else: cond += " AND n.{prop}{value[0]}{value[1]}".format( prop=prop, value=value, ) statement = "MATCH (n:%s ) WHERE %s RETURN n,labels(n)" % ( cypher_escape(label), cond) if limit: statement += " LIMIT %s" % limit response = graph.cypher.post(statement) for record in response.content["data"]: dehydrated = record[0] dehydrated.setdefault("metadata", {})["labels"] = record[1] yield graph.hydrate(dehydrated) response.close() def find_dict_one(graph, label, key_value=None): """ Find a single node by label and optional property. This method is intended to be used with a unique constraint and does not fail if more than one matching node is found. """ for node in find_dict(graph, label, key_value, limit=1): return node
using find_dict_one:
>>> a = find_dict_one(graph, 'Person', {'name': 'Lisa', 'age': 23}) >>> print(a) (n1:Person {age:23,name:"Lisa"})
Using find_dict with a tuple:
>>> a = find_dict(graph, 'Person', {'age': ('>', 21)}, 2) >>> for i in a: >>> print(i) (n2:Person {age:22,name:"Bart"}) (n1:Person {age:23,name:"Lisa"})
Using find_dict without a tuple:
>>> a = find_dict(graph, 'Person', {'age': 22}, 2) >>> for i in a: >>> print(i) (n2:Person {age:22,name:"Bart"})