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

Phép chiếu MongoDB của các mảng lồng nhau

Cập nhật năm 2017

Một câu hỏi hay như vậy xứng đáng có một câu trả lời hiện đại. Loại lọc mảng được yêu cầu thực sự có thể được thực hiện trong các bản phát hành MongoDB hiện đại, post 3.2 chỉ qua $match$project các giai đoạn đường ống, giống như hoạt động truy vấn đơn giản ban đầu dự định.

db.accounts.aggregate([
  { "$match": {
    "email" : "[email protected]",
    "groups": {
      "$elemMatch": { 
        "name": "group1",
        "contacts.localId": { "$in": [ "c1","c3", null ] }
      }
    }
  }},
  { "$addFields": {
    "groups": {
      "$filter": {
        "input": {
          "$map": {
            "input": "$groups",
            "as": "g",
            "in": {
              "name": "$$g.name",
              "contacts": {
                "$filter": {
                  "input": "$$g.contacts",
                  "as": "c",
                  "cond": {
                    "$or": [
                      { "$eq": [ "$$c.localId", "c1" ] },
                      { "$eq": [ "$$c.localId", "c3" ] }
                    ]
                  } 
                }
              }
            }
          }
        },
        "as": "g",
        "cond": {
          "$and": [
            { "$eq": [ "$$g.name", "group1" ] },
            { "$gt": [ { "$size": "$$g.contacts" }, 0 ] }
          ]
        }
      }
    }
  }}
])

Điều này sử dụng $filter$map toán tử để chỉ trả về các phần tử từ mảng đáp ứng các điều kiện và hiệu suất tốt hơn nhiều so với việc sử dụng $unwind . Vì các giai đoạn đường ống phản ánh hiệu quả cấu trúc của "truy vấn" và "dự án" từ .find() hoạt động, hiệu suất ở đây về cơ bản ngang bằng với như vậy và hoạt động.

Lưu ý rằng mục đích thực sự hoạt động ở đâu "trên toàn bộ tài liệu" để tập hợp các chi tiết lại với nhau từ "nhiều" tài liệu thay vì "một", thì điều này thường sẽ yêu cầu một số loại $unwind để làm như vậy, chẳng hạn như cho phép các mục mảng có thể truy cập được để "phân nhóm".

Về cơ bản đây là cách tiếp cận:

db.accounts.aggregate([
    // Match the documents by query
    { "$match": {
        "email" : "[email protected]",
        "groups.name": "group1",
        "groups.contacts.localId": { "$in": [ "c1","c3", null ] },
    }},

    // De-normalize nested array
    { "$unwind": "$groups" },
    { "$unwind": "$groups.contacts" },

    // Filter the actual array elements as desired
    { "$match": {
        "groups.name": "group1",
        "groups.contacts.localId": { "$in": [ "c1","c3", null ] },
    }},

    // Group the intermediate result.
    { "$group": {
        "_id": { "email": "$email", "name": "$groups.name" },
        "contacts": { "$push": "$groups.contacts" }
    }},

    // Group the final result
    { "$group": {
        "_id": "$_id.email",
        "groups": { "$push": {
            "name": "$_id.name",
            "contacts": "$contacts" 
        }}
    }}
])

Đây là "lọc mảng" trên nhiều kết quả phù hợp mà các khả năng chiếu cơ bản của .find() không làm được.

Bạn có các mảng "lồng vào nhau", do đó bạn cần xử lý $unwind hai lần. Cùng với các hoạt động khác.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB $ tháng

  2. Khung tổng hợp Mongodb | Nhóm trên nhiều giá trị?

  3. Mongoose - Làm thế nào để nhóm theo và cư trú?

  4. Trả về kết quả mongoose trong truy vấn tìm đến một biến

  5. Tài nguyên MongoDB hàng đầu