2011-09-12 67 views
17

Chúng tôi cần có thể nhanh chóng thực hiện các truy vấn trên toàn bộ bạn bè và bạn bè của người dùng. Điều này sẽ tương đối đơn giản trong một cơ sở dữ liệu quan hệ, nhưng tôi phần nào bị mắc kẹt theo cách tốt nhất để hoàn thành nó trong MongoDB. Chúng tôi lưu trữ các ID người dùng của bạn bè của người dùng trong một mảng trong tài liệu của người dùng, vì vậy giải pháp rõ ràng là để làm điều này:Mô hình hóa bạn bè của các mối quan hệ bạn bè trong MongoDB

  • Kéo tất cả các ID người dùng bạn từ người dùng doc
  • Kéo tất cả các mảng người bạn từ tài liệu người dùng của những người bạn đó (sử dụng $ trong truy vấn trên tất cả ID người bạn), kết hợp ứng dụng vào một bộ, sau đó kết hợp ứng dụng đó với ID người dùng cấp một để có được tất cả bạn bè và bạn bè của bạn bè
  • Sử dụng bộ đó thực hiện truy vấn cuối cùng (sử dụng $ in) trên tất cả bạn bè và bạn bè của bạn bè

Trong khi đơn giản, điều này có vẻ giống như một số lượng rất lớn của qua lại, so với những gì chúng ta có thể làm với một tham gia trong một cơ sở dữ liệu quan hệ. Có cách nào hiệu quả hơn để làm điều này trong MongoDB hay đây là vấn đề phù hợp nhất cho RDBMS?

Trả lời

7

này có vẻ như một số lượng lớn qua lại, so với những gì chúng ta có thể làm với một tham gia trong một cơ sở dữ liệu quan hệ

Đây là tất cả đều rất tương đối. Giả định cơ bản của bạn về việc tìm nạp "bạn bè của bạn bè của bạn bè" là chính xác, đó là một vài bước nhảy và một vài "bộ nhớ" trong bộ nhớ.

Tuy nhiên, từ quan điểm thô của "tổng công việc đã hoàn thành", điều này không khác với những gì bạn đã làm với SQL. Vâng, đó là một truy vấn SQL tương đối đơn giản, nhưng bản thân máy chủ vẫn phải làm về cơ bản cùng một lượng công việc, cho hay lấy một số lưu lượng mạng nào đó.

Có cách nào hiệu quả hơn để thực hiện việc này trong MongoDB hay đây có phải là vấn đề phù hợp nhất với RDBMS không?

Có cách nào tốt hơn trong MongoDB không? Chắc là không. Nhưng việc "tự kết nối" trong SQL không dễ dàng mở rộng trên nhiều máy chủ. Trong thực tế, cố gắng thực hiện điều này trên nhiều máy chủ về cơ bản sẽ biến thành một quá trình tương tự với tiến trình MongoDB.

Về mặt kỹ thuật, đây là công việc được thực hiện tốt nhất bởi Cơ sở dữ liệu đồ thị không phải là MongoDB hay RDBMS.

Đối với đồ thị Cơ sở dữ liệu bạn có thể xem Trinity for .NET hoặc NEO4J.

2

Tôi tin rằng đây là cái gì đó được xử lý tốt hơn bởi RDBMS (chặn DB đồ thị) vì bạn rõ ràng cần thực hiện thao tác "nối". Mặc dù RDBMS có thể thực hiện nó theo cùng một cách, nhưng nó có thể thực hiện việc kết nối hiệu quả hơn và phân phối thông tin hiệu quả hơn MongoDB.

Với điều đó đã nói, chi phí thực hiện truy vấn "nối" nguyên tử có thể chứng minh quá tốn kém nếu bạn có một cụm lớn các nút db và một lượng lớn người dùng.

Nếu bạn không lo lắng về tính nhất quán và nguyên tử của truy vấn, và tất cả những gì bạn muốn là ngăn chặn việc chuyển đổi giữa ứng dụng và DB, bạn có thể viết một hàm JavaScript sẽ thực hiện toàn bộ truy vấn trên MongoDB, hoặc sử dụng một hoạt động MapReduce cho các truy vấn phân tán hiệu quả hơn.

13

Tôi đã hỏi Eliot Horowitz câu hỏi rất giống này gần đây tại hội nghị MongoDB SV. Ông cho biết cách ông sẽ cấu trúc nó là để lưu trữ mỗi người dùng bạn bè như các tài liệu nhúng trong mỗi người dùng. Ví dụ, cấu trúc có thể trông như thế này:

{ 
    _id : ObjectId("4e77bb3b8a3e000000004f7a"), 
    username : "alex", 
    friends : ["283956723823626626aa", "226567377578888888as", "8738783888aas88a8a88" ] 
} 

sau đó bạn có thể có một chỉ mục trên user.friends

http://www.mongodb.org/display/DOCS/Indexes#Indexes-IndexingArrayElements

"Khi giá trị được lưu trữ của một tài liệu cho một lĩnh vực chủ chốt chỉ số là một mảng , MongoDB lập chỉ mục từng phần tử của mảng. Xem trang Multikeys để biết thêm thông tin. "

như vậy để tất cả "alex" 's bạn bè tôi chỉ có thể làm:

db.user.find ({ 'bạn bè': '4e77bb3b8a3e000000004f7a'});

+1

Điều này giả định rằng mối quan hệ bạn bè luôn luôn là lẫn nhau ... nếu alex là bạn với jon, hơn jon cũng phải là bạn với alex. – Jay

+0

Điều gì về việc kết bạn với nhau? –

+0

Xem https://gist.github.com/levicook/4132037 cho bạn bè chung – rodi

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