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

$ lookup trên ObjectId's trong một mảng

Bản cập nhật năm 2017

$ lookup hiện có thể sử dụng trực tiếp một mảng làm trường cục bộ. $unwind không còn cần thiết nữa.

Câu trả lời cũ

$lookup giai đoạn đường ống tổng hợp sẽ không hoạt động trực tiếp với một mảng. Mục đích chính của thiết kế là cho "kết nối bên trái" như một kiểu kết hợp "một đến nhiều" (hoặc thực sự là một "tra cứu") trên dữ liệu liên quan có thể có. Nhưng giá trị được dự định là số ít và không phải là một mảng.

Do đó, bạn phải "khử chuẩn hóa" nội dung trước khi thực hiện $lookup hoạt động để điều này hoạt động. Và điều đó có nghĩa là sử dụng $unwind :

db.orders.aggregate([
    // Unwind the source
    { "$unwind": "$products" },
    // Do the lookup matching
    { "$lookup": {
       "from": "products",
       "localField": "products",
       "foreignField": "_id",
       "as": "productObjects"
    }},
    // Unwind the result arrays ( likely one or none )
    { "$unwind": "$productObjects" },
    // Group back to arrays
    { "$group": {
        "_id": "$_id",
        "products": { "$push": "$products" },
        "productObjects": { "$push": "$productObjects" }
    }}
])

Sau khi $lookup khớp với từng thành viên mảng, kết quả là chính một mảng, vì vậy bạn $unwind một lần nữa và $group đến $push mảng mới cho kết quả cuối cùng.

Lưu ý rằng bất kỳ kết quả khớp "kết hợp trái" nào không được tìm thấy sẽ tạo ra một mảng trống cho "productObjects" trên sản phẩm nhất định và do đó phủ định tài liệu cho phần tử "product" khi $unwind thứ hai được gọi là.

Mặc dù ứng dụng trực tiếp vào một mảng sẽ rất hay, nhưng đó chỉ là cách ứng dụng này hiện đang hoạt động bằng cách so khớp một giá trị đơn lẻ với một giá trị có thể có.

Dưới dạng $lookup về cơ bản là rất mới, nó hiện hoạt động như quen thuộc với những người đã quen thuộc với mongoose như một "phiên bản dành cho người nghèo" của .populate() phương pháp được cung cấp ở đó. Sự khác biệt là $lookup cung cấp xử lý "phía máy chủ" đối với "tham gia" trái ngược với trên máy khách và một số "thời hạn" trong $lookup hiện đang thiếu cái gì .populate() cung cấp (chẳng hạn như nội suy tra cứu trực tiếp trên một mảng).

Đây thực sự là một vấn đề được chỉ định để cải thiện SERVER-22881, vì vậy nếu may mắn, điều này sẽ xảy ra với bản phát hành tiếp theo hoặc ngay sau đó.

Theo nguyên tắc thiết kế, cấu trúc hiện tại của bạn không tốt hay xấu, mà chỉ phụ thuộc vào chi phí khi tạo bất kỳ "nối" nào. Do đó, nguyên tắc cơ bản của MongoDB khi mới bắt đầu được áp dụng, trong đó nếu bạn "có thể" sống với dữ liệu "được kết hợp trước" trong một bộ sưu tập, thì tốt nhất là nên làm như vậy.

Một điều khác có thể nói về $lookup như một nguyên tắc chung, là mục đích của "tham gia" ở đây là hoạt động theo cách khác với được hiển thị ở đây. Vì vậy, thay vì giữ "id liên quan" của các tài liệu khác trong tài liệu "gốc", nguyên tắc chung hoạt động tốt nhất là nơi "tài liệu liên quan" chứa tham chiếu đến "tài liệu gốc".

Vì vậy, $lookup có thể nói là "hoạt động tốt nhất" với "thiết kế quan hệ" ngược lại với cách một cái gì đó như mongoose .populate() thực hiện tham gia phía khách hàng của nó. Thay vào đó, bằng cách lý tưởng hóa "một" trong mỗi "nhiều", sau đó bạn chỉ cần lấy các mục liên quan mà không cần $unwind mảng đầu tiên.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Xử lý các thay đổi giản đồ trong Mongoose

  2. pymongo:MongoClient hoặc Kết nối

  3. Làm cách nào để bạn kết nối với bản sao từ vỏ MongoDB?

  4. MongoDB $ mẫu

  5. Làm cách nào để thực thi truy vấn gốc MongoDB (JSON) chỉ sử dụng mongo-java-driver?