2017-07-03 18 views
6

Tôi có một đồ thị neo4j trông như thế này:Cypher: Tìm bất kỳ con đường giữa các nút

Graph overview

Nodes:

  1. xanh Nodes: Tài khoản
  2. Red Nodes: PhoneNumber
  3. Nút màu xanh lá cây: Email

thiết kế Graph:

  • (: PhoneNumber) - [: PART_OF] -> (: Account)
  • (: Email) - [: PART_OF] -> (: Account)

vấn đề tôi đang cố gắng để giải quyết là để

Tìm bất kỳ con đường mà tồn tại giữa account1 và Account2.

Đây là những gì tôi đã cố gắng cho đến nay không có thành công:

  1. Đội hình thi đấu p = shortestPath ((a1: Account {accId: '1234'}) - [] - (a2: Account { accId: '5678'})) RETURN p;
  2. MATCH p = shortestPath ((a1: Tài khoản {accId: '1234'}) - [: PART_OF] - (a2: Tài khoản {accId: '5678'})) RETURN p;
  3. MATCH p = shortestPath ((a1: Tài khoản {accId: '1234'}) - [*] - (a2: Tài khoản {accId: '5678'})) RETURN p;
  4. MATCH p = (a1: Tài khoản {accId: '1234'}) < - [: PART_OF * 1..100] - (n) - [: PART_OF] -> (a2: Tài khoản {accId: '5678' }) TRẢ LẠI p;
  5. Các truy vấn giống như trên mà không có cuộc gọi hàm đường dẫn ngắn nhất.

Bằng cách xem biểu đồ Tôi có thể thấy có một đường dẫn giữa 2 nút này nhưng không có truy vấn nào của tôi cho bất kỳ kết quả nào. Tôi chắc chắn đây là một truy vấn rất đơn giản nhưng mới với Cypher, tôi đang gặp khó khăn trong việc tìm ra giải pháp đúng. Bất kỳ trợ giúp được đánh giá cao.

Cảm ơn.

+0

Bạn có thể cung cấp thêm chi tiết về điều gì xảy ra khi bạn chạy các truy vấn này không? –

Trả lời

4

Tất cả các truy vấn đó đều nằm dọc dòng bên phải nhưng cần một số tinh chỉnh để thực hiện công việc. Tuy nhiên, về lâu dài, để có được một hệ thống tốt hơn để dễ dàng tìm kiếm các kết nối giữa các tài khoản, có thể bạn sẽ muốn cấu trúc lại đồ thị của mình.

Giải pháp cho Bây giờ là: Làm cho truy vấn của bạn

Đường dẫn giữa bất kỳ hai (n:Account) nút trong đồ thị của bạn sẽ trông giống như thế này:

(a1:Account)<-[:PART_OF]-(:Email)-[:PART_OF]->(ai:Account)<-[:PART_OF]-(:PhoneNumber)-[:PART_OF]->(a2:Account)

Kể từ khi bạn chỉ có một loại mối quan hệ trong biểu đồ của bạn, do đó, hai nút này sẽ được kết nối bằng một số mẫu không xác định như sau:

<-[:PART_OF]-(:Email)-[:PART_OF]->

hoặc

<-[:PART_OF]-(:PhoneNumber)-[:PART_OF]->

Vì vậy, hai nút của bạn sẽ được kết nối thông qua một số không xác định của trung gian (:Account), (:Email), hoặc (:PhoneNumber) hạch tất cả nối với nhau bằng các mối quan hệ -[:PART_OF]- hướng xen kẽ. Thật không may cho kiến ​​thức của tôi (và tôi muốn được sửa chữa ở đây), bằng cách sử dụng cypher thẳng bạn không thể tìm kiếm một mô hình lặp đi lặp lại như thế này trong biểu đồ hiện tại của bạn. Vì vậy, bạn sẽ chỉ cần sử dụng tìm kiếm không được tìm kiếm, để tìm các nút (a1:Account)(a2:Account) được kết nối thông qua các mối quan hệ -[:PART_OF]-. Vì vậy, ở cái nhìn đầu tiên truy vấn của bạn sẽ trông như thế này:

MATCH p=shortestPath((a1:Account { accId: {a1_id} })-[:PART_OF*]-(a2:Account { accId: {a2_id} })) 
RETURN * 

(chú ý ở đây tôi đã sử dụng cypher parameters chứ không phải là số nguyên bạn đặt trong các bài bản gốc)

Đó là rất giống với truy vấn # 3 của bạn , nhưng, như bạn đã nói - nó không hoạt động. Tôi đoán điều gì xảy ra là nó không trả lại kết quả, hoặc trả về một ngoại lệ bộ nhớ? Vấn đề là vì biểu đồ của bạn có đường tròn và nó sẽ khớp với đường dẫn có độ dài bất kỳ, thuật toán khớp sẽ theo vòng tròn cho đến khi hết bộ nhớ. Vì vậy, bạn muốn đặt giới hạn, như bạn có trong truy vấn # 4, nhưng không có chỉ đường (đó là lý do tại sao truy vấn đó không hoạt động).

Vì vậy, hãy đặt giới hạn. Giới hạn 100 mối quan hệ của bạn hơi nhỏ ở phía bên lớn, đặc biệt là trong biểu đồ chu kỳ (tức là, một biểu đồ có vòng tròn) và có khả năng khớp với khu vực có 2^100 đường dẫn.

Như một quy tắc ngón tay cái (rất tùy ý), bất kỳ truy vấn nào có chiều dài đường dẫn không được khai thác và không được khai thác lớn hơn 5 hoặc 6 có thể bắt đầu gây ra sự cố trừ khi bạn rất cẩn thận với thiết kế biểu đồ của mình. Trong ví dụ của bạn, có vẻ như hai nút này được kết nối thông qua chiều dài đường dẫn 8. Chúng ta cũng biết rằng đối với bất kỳ hai nút nào, chiều dài đường dẫn tối thiểu cho trước sẽ là hai (tức là, hai mối quan hệ -[:PART_OF]-, một trong và một nút có nhãn là :Email hoặc :PhoneNumber) và rằng bất kỳ hai tài khoản nào, nếu được liên kết, sẽ được liên kết qua một số mối quan hệ đồng đều. Vì vậy, lý tưởng là chúng tôi đã đặt độ dài mối quan hệ giữa 2 và 10. Tuy nhiên, chức năng shortestPath() của cypher chỉ hỗ trợ các đường có độ dài tối thiểu là 0 hoặc 1, vì vậy tôi đã đặt nó từ 1 đến 10 trong ví dụ dưới đây (mặc dù chúng tôi biết rằng trên thực tế, con đường ngắn nhất có chiều dài ít nhất là hai).

MATCH p=shortestPath((a1:Account { accId: {a1_id} })-[:PART_OF*1..10]-(a2:Account { accId: {a2_id} })) 
RETURN * 

Hy vọng rằng, điều này sẽ làm việc với các trường hợp sử dụng của bạn, nhưng hãy nhớ, nó vẫn có thể rất nhớ chuyên sâu để chạy trên một đồ thị lớn.

dài Giải pháp hạn: Graph Refactor và/hoặc Sử dụng APOC

Tùy thuộc vào trường hợp sử dụng của bạn, một giải pháp dài hạn tốt hơn hoặc sẽ được cấu trúc lại đồ thị của bạn được cụ thể hơn về các mối quan hệ để tăng tốc độ thời gian truy vấn khi bạn chỉ muốn tìm tài khoản được liên kết qua email hoặc số điện thoại - nghĩa là -[:ACCOUNT_HAS_EMAIL]--[:ACCOUNT_HAS_PHONE]-. Sau đó, bạn cũng có thể muốn sử dụng số shortest path algorithms hoặc path finder functions của APOC, rất có thể sẽ trả lại kết quả nhanh hơn sử dụng cypher và cho phép bạn cụ thể hơn về các loại mối quan hệ khi biểu đồ của bạn mở rộng để nhận nhiều dữ liệu hơn.

+1

Cảm ơn Dom, điều này đã làm việc như sự quyến rũ. Bây giờ tôi đã hiểu được lỗi cơ bản trong thiết kế đồ thị của tôi. Tôi sẽ sửa chữa thiết kế và thử APOC. Chưa bao giờ thử chúng trước đây. Cảm ơn một lần nữa. – Agandalf

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