MongoDB 连接两个具有 JSON 数组数据的集合

MongoDB join two collections having JSON array data

我能够为使用 $lookup 的普通单键值连接编写查询。但是我的场景有点复杂,不知道如何实现。

产品:

{
    "_id": ObjectId("6200a77598412e443c03f0ee"),
    "name": "1000",
    "sku_code": "22",
    "field_values": [{
        "field_id": ObjectId("61fd34cbbc787e45d256a270"),
        "key": "P4YZRK71CZAQ8IXJ3",
        "value": "54"
    }, {
        "field_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
        "key": "SF_10KRUMSESSIONSPERMONTH",
        "value": "34"
    }]
}

字段:

{
    "_id": ObjectId("61fb77b1384e2635f8a2d1e9"),
    "description": "sf_infrastructureFunction__c",
    "is_read_only": false,
    "is_required": false,
    "name": "sf_infrastructureFunction",
    "key": "SF_INFRASTRUCTUREFUNCTION",
    "type": "number"
}, {
    "_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
    "default": "123",
    "description": "sf_10KRumSessionsPerMonth__c",
    "is_read_only": false,
    "is_required": false,
    "name": "sf_10KRumSessionsPerMonth",
    "key": "SF_10KRUMSESSIONSPERMONTH",
    "type": "number"
}, {
    "_id": ObjectId("61fd34cbbc787e45d256a270"),
    "description": "UKXNVYBF7AXE1VOUH",
    "is_read_only": false,
    "is_required": true,
    "name": "P4YZRK71CZAQ8IXJ3",
    "key": "P4YZRK71CZAQ8IXJ3",
    "type": "number"
}

产品 (6200a77598412e443c03f0ee) 的最终预期输出:

{
    "_id": ObjectId("61fb77b1384e2635f8a2d1e9"),
    "description": "sf_infrastructureFunction__c",
    "is_read_only": false,
    "is_required": false,
    "name": "sf_infrastructureFunction",
    "key": "SF_INFRASTRUCTUREFUNCTION",
    "type": "number",
}, {
    "_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
    "default": "123",
    "description": "sf_10KRumSessionsPerMonth__c",
    "is_read_only": false,
    "is_required": false,
    "name": "sf_10KRumSessionsPerMonth",
    "key": "SF_10KRUMSESSIONSPERMONTH",
    "type": "number",
    "field_data" : {
        "key": "SF_10KRUMSESSIONSPERMONTH",
        "value": "34"
    }
}, {
    "_id": ObjectId("61fd34cbbc787e45d256a270"),
    "description": "UKXNVYBF7AXE1VOUH",
    "is_read_only": false,
    "is_required": true,
    "name": "P4YZRK71CZAQ8IXJ3",
    "key": "P4YZRK71CZAQ8IXJ3",
    "type": "number",
    "field_data" : {
        "key": "P4YZRK71CZAQ8IXJ3",
        "value": "54"
    }
}

请注意示例输出中的第一个 JSON,产品尚未为该字段存储任何 field_values。总的来说,我想要所有字段数据及其特定产品 ID 的值,如果它没有值,则字段的简单配置。

像这样:

db.field.aggregate([
{
 "$lookup": {
  "from": "product",
  "localField": "_id",
  "foreignField": "field_values.field_id",
  "as": "field_data"
 }
 },
 {
   $unwind: {
    path: "$field_data",
    preserveNullAndEmptyArrays: true
 }
 },
 {
  "$addFields": {
  "field_data": {
    "$filter": {
      "input": "$field_data.field_values",
      "as": "fv",
      "cond": {
        $eq: [
          "$$fv.field_id",
          "$_id"
        ]
       }
      }
     }
    }
   },
   {
    $addFields: {
     field_data: {
      $cond: {
       if: {
        $eq: [
          "$field_data",
          null
        ]
       },
       then: "$$REMOVE",
       else: "$field_data"
      }
     }
    }
   }
 ])

解释:

  1. $lookup 将产品添加到字段文档
  2. $unwind 展平结果数组(它包含产品文档)并保留空元素
  3. $filter 只保留匹配的产品。
  4. 删除那些为空的产品的空 field_data。

playground