MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Cách hiệu quả nhất để lưu trữ các danh mục lồng nhau (hoặc dữ liệu phân cấp) trong Mongo?

Điều đầu tiên bạn muốn quyết định là chính xác loại cây bạn sẽ sử dụng.

Điều quan trọng cần xem xét là dữ liệu và các mẫu truy cập của bạn. Bạn đã tuyên bố rằng 90% công việc của bạn sẽ là truy vấn và theo âm thanh của nó (thương mại điện tử), các bản cập nhật sẽ chỉ do quản trị viên chạy, rất hiếm khi xảy ra.

Vì vậy, bạn muốn một giản đồ cung cấp cho bạn khả năng truy vấn nhanh chóng trên trẻ em thông qua một đường dẫn, tức là:Thể thao -> Bóng rổ -> Nam, Thể thao -> Quần vợt -> Nữ và không thực sự cần mở rộng quy mô để cập nhật.

Như bạn đã chỉ ra rất đúng MongoDB có một trang tài liệu tốt cho việc này: https://docs.mongodb.com/manual/application/data-models-tree-structures/ theo đó 10gen thực sự chỉ ra các mô hình và phương pháp lược đồ khác nhau cho cây và mô tả những thăng trầm chính của chúng.

Một trong những điều sẽ thu hút sự chú ý nếu bạn muốn truy vấn dễ dàng là các đường dẫn cụ thể hóa: https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Đây là một phương pháp rất thú vị để xây dựng cây vì để truy vấn theo ví dụ bạn đã đưa ra ở trên thành "Womens" trong "Tennis", bạn có thể chỉ cần thực hiện một regex cố định trước (có thể sử dụng chỉ mục: http://docs.mongodb.org/manual/reference/operator/regex/ ) như vậy:

db.products.find({category: /^Sports,Tennis,Womens[,]/})

để tìm tất cả các sản phẩm được liệt kê dưới một con đường nhất định trên cây của bạn.

Rất tiếc, mô hình này thực sự kém cập nhật, nếu bạn di chuyển một danh mục hoặc thay đổi tên của nó, bạn phải cập nhật tất cả các sản phẩm và có thể có hàng nghìn sản phẩm trong một danh mục.

Phương pháp tốt hơn sẽ là chứa cat_id trên sản phẩm và sau đó tách các danh mục thành một bộ sưu tập riêng biệt với giản đồ:

{
    _id: ObjectId(),
    name: 'Women\'s',
    path: 'Sports,Tennis,Womens',
    normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}

Vì vậy, bây giờ các truy vấn của bạn chỉ liên quan đến bộ sưu tập danh mục, điều này sẽ làm cho chúng nhỏ hơn và hiệu quả hơn nhiều. Ngoại lệ cho điều này là khi bạn xóa một danh mục, các sản phẩm sẽ vẫn cần chạm vào.

Vì vậy, một ví dụ về việc thay đổi "Tennis" thành "Badmin":

db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
    doc.path = doc.path.replace(/,Tennis/, ",Badmin");
    db.categories.save(doc);
});

Thật không may, MongoDB không cung cấp phản ánh tài liệu trong truy vấn vào lúc này, vì vậy bạn phải kéo chúng ra phía máy khách, điều này hơi khó chịu, tuy nhiên hy vọng rằng nó sẽ không dẫn đến quá nhiều danh mục được đưa trở lại.

Và về cơ bản đây là cách nó hoạt động thực sự. Hơi phiền khi cập nhật nhưng sức mạnh của việc có thể truy vấn ngay lập tức trên bất kỳ đường dẫn nào bằng cách sử dụng một chỉ mục phù hợp hơn với trường hợp của bạn, tôi tin rằng.

Tất nhiên, lợi ích bổ sung là lược đồ này tương thích với các mô hình tập hợp lồng nhau: http://en.wikipedia .org / wiki / Nested_set_model Điều mà tôi nhận thấy hết lần này đến lần khác thật tuyệt vời đối với các trang web thương mại điện tử, ví dụ:Quần vợt có thể nằm trong cả "Thể thao" và "Giải trí" và bạn muốn có nhiều con đường tùy thuộc vào nơi người dùng đến.

Lược đồ cho các đường dẫn cụ thể hóa dễ dàng hỗ trợ điều này bằng cách chỉ cần thêm một path khác , thật đơn giản.

Hy vọng nó có ý nghĩa, một khoảng thời gian khá dài ở đó.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB Atlas lỗi:giản đồ không hợp lệ, mongodb mong đợi

  2. MongoDB:Cách nhận độ chính xác N số thập phân trong một truy vấn

  3. Có thể chuyển số bị chia và số bị chia của toán tử truy vấn $ mod của MongoDB không?

  4. Mongoid / Mongodb và truy vấn tài liệu nhúng

  5. Cách cập nhật một mảng tài liệu con trên bộ sưu tập MongoDB trong MeteorJS