2016-08-03 15 views
5

Tôi có biểu đồ liên kết nút đơn giản trong ArangoDB. Làm thế nào tôi có thể đi qua từ 1 nút được chọn trước và trả về tất cả các nút có liên quan đến nó?ArangoDB: Nhận mọi nút, theo bất kỳ cách nào liên quan đến nút đã chọn

Ví dụ: A → B, B → C, C → D, C → E, F → B, F → E

Chọn ai trong số họ sẽ trả về kết quả tương tự (tất cả trong số họ).

Tôi rất mới đối với ArangoDB.

Trả lời

9

Những gì bạn cần là AQL graph traversal, có sẵn từ ArangoDB 2.8. Các phiên bản cũ hơn cung cấp một tập hợp các hàm liên quan đến biểu đồ, nhưng việc truyền tải AQL gốc nhanh hơn, linh hoạt hơn và các hàm đồ thị không còn khả dụng bắt đầu với 3.0.


AQL traversal cho phép bạn làm theo các cạnh nối với đỉnh bắt đầu, đến độ sâu khác nhau. Mỗi đỉnh gặp phải có thể được truy cập, ví dụ: để lọc hoặc để xây dựng một kết quả, cũng như các cạnh dẫn bạn đến đỉnh này và đường dẫn đầy đủ từ đầu đến cuối bao gồm cả, đỉnh và cạnh.

Trong trường hợp của bạn, chỉ cần trả lại tên của các đỉnh truy cập. Bạn có thể chạy các truy vấn AQL sau, giả sử có một bộ sưu tập tài liệu node và bộ sưu tập links một cạnh và chúng chứa dữ liệu cho biểu đồ này:

Example Graph

// follow edges ("links" collection) in outbound direction, starting at A 
FOR v IN OUTBOUND "node/A" links 
    // return the key (node name) for every vertex we see 
    RETURN v._key 

này sẽ chỉ trả lại [ "B" ], bởi vì độ sâu traversal là hoàn toàn 1..1 (min = 1, max = 1). Nếu chúng tôi tăng độ sâu tối đa, thì chúng tôi cũng có thể bao gồm các nút được kết nối gián tiếp:

FOR v IN 1..10 OUTBOUND "node/A" links 
    RETURN v._key 

Điều này sẽ cung cấp cho chúng tôi [ "B", "C", "D", "E"]. Nếu chúng ta nhìn vào biểu đồ, điều này là chính xác: chúng ta chỉ theo các cạnh điểm từ đỉnh chúng ta đến từ một đỉnh khác (hướng của mũi tên). Để làm được điều ngược lại, chúng ta có thể sử dụng INBOUND, nhưng trong trường hợp của bạn, chúng tôi muốn bỏ qua sự chỉ đạo của cạnh và làm theo anyway:

FOR v IN 1..10 ANY "node/A" links 
    RETURN v._key 

Kết quả có thể là một chút ngạc nhiên lúc đầu:
[ "B", "C", "D", "E", "F", "B", "F", "E", "C", "D", "B" ]

Chúng tôi thấy các nút trùng lặp được trả lại. Lý do là có nhiều đường dẫn từ A đến C ví dụ (thông qua B và cũng thông qua B-F-E), và truy vấn trả về nút cuối cùng của mỗi đường dẫn như biến v. (Nó không thực sự xử lý tất cả con đường có thể lên đến độ sâu tối đa là 10, nhưng bạn có thể thiết lập các tùy chọn traversal OPTIONS {uniqueEdges: "none"} để làm như vậy.)

Nó có thể giúp đỡ để trở về con đường traversal định dạng để hiểu rõ hơn về những gì là xảy ra (tức là cách các nút được đạt):

FOR v, e, p IN 1..10 ANY "node/A" links OPTIONS {uniqueEdges: "path"} 
    RETURN CONCAT_SEPARATOR(" - ", p.vertices[*]._key) 

Kết quả:

[ 
    "A - B", 
    "A - B - C", 
    "A - B - C - D", 
    "A - B - C - E", 
    "A - B - C - E - F", 
    "A - B - C - E - F - B", 
    "A - B - F", 
    "A - B - F - E", 
    "A - B - F - E - C", 
    "A - B - F - E - C - D", 
    "A - B - F - E - C - B" 
] 

có một chu kỳ trong đồ thị, nhưng không thể có một vòng lặp vô hạn vì độ sâu tối đa vượt quá phía sau er 10 bước nhảy.Nhưng như bạn có thể thấy ở trên, nó thậm chí không đạt đến độ sâu 10, nó thay vì dừng lại vì tùy chọn (mặc định) là không theo các cạnh hai lần trên mỗi đường dẫn (uniqueEdges: "path").

Dù sao, đây không phải là kết quả mong muốn. Một mẹo rẻ sẽ là sử dụng RETURN DISTINCT, COLLECT hoặc một cái gì đó tương tự để loại bỏ các bản sao. Nhưng chúng ta nên tinh chỉnh các tùy chọn traversal, để không làm theo các cạnh không cần thiết.

uniqueEdges: "global" sẽ vẫn bao gồm nút B hai lần, nhưng uniqueVertices: "global" cho kết quả mong muốn. Ngoài ra, bạn có thể sử dụng bfs: true cho tìm kiếm theo chiều rộng đầu tiên trong trường hợp này. Sự khác biệt là đường dẫn đến nút F ngắn hơn (A-B-F thay vì A-B-C-E-F). Nói chung, các tùy chọn chính xác bạn nên sử dụng phần lớn phụ thuộc vào tập dữ liệu và các câu hỏi bạn có.

Có thêm một vấn đề cần giải quyết: quá trình truyền tải không bao gồm đỉnh bắt đầu (trừ trong p.vertices[0] cho mọi đường dẫn). Điều này có thể dễ dàng được giải quyết bằng ArangoDB 3.0 or later bằng cách thiết lập độ sâu tối thiểu để 0:

FOR v IN 0..10 ANY "node/A" links OPTIONS {uniqueVertices: "global"} 
    RETURN v._key 

[ "A", "B", "C", "D", "E", "F" ]

Để xác minh rằng tất cả các nút từ A đến F được trả về, không phụ thuộc vào đỉnh đầu, chúng ta có thể phát hành truy vấn thử nghiệm sau:

FOR doc IN node 
    RETURN (
     FOR v IN 0..10 ANY doc links OPTIONS {uniqueVertices: "global"} 
      SORT v._key 
      RETURN v._key 
    ) 

Tất cả các mảng phụ phải giống nhau. Xóa thao tác SORT nếu bạn muốn các tên nút được trả về theo thứ tự truyền tải. Hy vọng điều này sẽ giúp =)

+0

Đó là một câu trả lời đáng kinh ngạc.Cảm ơn bạn rất nhiều. Nó thực sự hữu ích cho Arango giả như bản thân mình để có tất cả mọi thứ giải thích một cách rõ ràng với ví dụ –

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