2015-01-06 17 views
5

Tôi có một số rắc rối với py2neo tìm và find_one (http://py2neo.org/2.0/essentials.html)py2neo: Graph.find_one với nhiều khóa/giá trị

Những gì tôi muốn ở Cypher là:

MATCH (p:Person) WHERE p.name='Alice' AND p.age=22 RETURN p 

Say, nơi có nhiều hơn một bộ khóa/giá trị (ví dụ: nếu có nhiều hơn một 'Alice' trong biểu đồ).

Vấn đề của tôi là tôi không biết những gì để cung cấp cho graph.find_one, mã làm việc là:

graph.find_one('Person', 'name', 'Alice') 

Những gì tôi muốn là một cái gì đó tương tự (Đây không phải là làm việc!):

graph.find_one('Person', {'name': 'Alice', 'age': 22}) 

Một giải pháp có thể (xấu) là tạo biểu đồ.find và sau đó lặp lại các thuộc tính kết quả và tìm tuổi, nhưng tôi không thích giải pháp đó.

Phần thưởng: Có thể với graph.find để làm điều gì đó như tuổi> 25 không?


EDIT: Mới "giải pháp"

find_person = "MATCH (p: Person) WHERE p.name = {N} VÀ p.age = {A} RETURN p"

>>> tx = graph.cypher.begin() 
>>> tx.append(find_person, {'N': 'Alice', 'A': 22}) 
>>> res = tx.process() 
>>> print(res[0][0][0]) 
(n423:Person {age:22,name:"Lisa"}) 

những gì tôi không thích về vấn đề này là tôi bỏ lỡ Lưu ý đối tượng, (và tôi không hiểu đầy đủ về RecordListList, và làm thế nào để di chuyển nó nicley)

Trả lời

2

Dựa trên câu trả lời @elyase và py2neo.Graph.find ban đầu, tôi đã thực hiện mã này. Xin vui lòng nhận xét và cải thiện .. :-)

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 

sử dụng find_dict_one:

>>> a = find_dict_one(graph, 'Person', {'name': 'Lisa', 'age': 23}) 
>>>  print(a) 
(n1:Person {age:23,name:"Lisa"}) 

Sử dụng find_dict với 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"}) 

Sử dụng find_dict mà không tuple:

>>> a = find_dict(graph, 'Person', {'age': 22}, 2) >>> for i in a: 
>>>  print(i) 
(n2:Person {age:22,name:"Bart"}) 
4

Nếu bạn nhìn vào source code bạn sẽ thấy rằng không may findfind_one không hỗ trợ loại truy vấn. Bạn nên trực tiếp sử dụng các Cypher interface:

d = {'name': 'Alice', 'age' : 22} 

# quote string values 
d = {k:"'{}'".format(v) if isinstance(v, basestring) else v 
        for k,v in d.items()} 

cond = ' AND '.join("p.{}={}".format(prop, value) for prop, value in d.items()) 

query = "MATCH (p:Person) {condition} RETURN p" 
query = query.format(condition=cond) 
# "MATCH (p:Person) p.age=22 AND p.name='Alice' RETURN p" 
results = graph.cypher.execute(query) 
+1

Cảm ơn câu trả lời của bạn .. :-) Vấn đề với t giải pháp mũ là nó thực sự chiếu xạ quá khứ trong các thông số. Tôi đã thực hiện một chỉnh sửa cho bài đăng, với một ý tưởng tốt hơn một chút, nhưng vẫn chưa có. –

+0

@ThomasRepsdorph, tôi cập nhật câu trả lời của tôi để giải thích làm thế nào để vượt qua các thông số, điều này về cơ bản là những gì 'find' nên làm, bạn có thể gửi một yêu cầu kéo một khi bạn nhận được nó làm việc. – elyase

+0

Âm thanh vui nhộn, tôi sẽ cố gắng .. :-D Và cảm ơn sự giúp đỡ của bạn. –

Các vấn đề liên quan