MongoDB 仅查找某些值

MongoDB lookup only on certain values

我有以下数据库数据和查询:https://mongoplayground.net/p/8jx-oejWQV7.

我正在尝试仅对 questions.value 类型的 ObjectId 执行查找。并希望查询中的 return 看起来像这样:

[
  {
    "_id": ObjectId("60d9c9ff7fde704f28e89040"),
    "questions": [
      {
        "id": "607569f06df0a80197227d06",
        "value": "A String Value 1"
      },
      {
        "id": "607569f78f403f67dd1fefed",
        "value": "A String value 2"
      },
      {
        "id": "607569f78f403f67dd1fefef",
        "value": "A String value 3"
      },
      {
        "id": "607569e0701e55c65eae7554",
        "value": "C"
      },
      {
        "id": "607569e86b5b2a2175cce0f0",
        "value": "C"
      },
      {
        "id": "607569fff2597be5ff2444fd",
        "value": "B"
      },
      {
        "id": "607569fff2597be5ff2444fc",
        "value": "A"
      }
    ]
  }
]

我该如何重新添加非 'looked up' 值?

谢谢!

在您的查询中,问题与 $unwind 有关,因此您删除了空数组值。 您需要使用 $ifNull 更新您的查询以保留初始数组中的值,但一般答案是 您需要使用 preserveNullAndEmptyArrays

...
  {
    $project: {
      "questions.id": 1,
      "questions.value": "$questions.value.displayLabel"
    }
  },
  {
    $unwind: {
      path: "$questions.value",
      preserveNullAndEmptyArrays: true
    }
  },

您需要更正您的查询,

  • $unwind - 按原样放置
  • $lookup - 按原样放置,但将 as 字段重命名为 refValue
  • $addFields 检查条件,如果结果为空数组,则保持相同的值,否则使用 $first 运算符
  • 替换为查找值
  • $unset 删除 refValue 现在不需要
  • $group - 按原样放置但添加 status 字段
db.products.aggregate([
  { $unwind: "$questions" },
  {
    $lookup: {
      from: "ex_ref_data",
      let: { questionValue: "$questions.value" },
      pipeline: [
        { $match: { $expr: { $eq: ["$$questionValue", "$_id"] } } },
        {
          $project: {
            displayLabel: 1,
            _id: 0
          }
        }
      ],
      as: "questions.refValue"
    }
  },
  {
    $addFields: {
      "questions.value": {
        $cond: [
          { $ne: ["$questions.refValue", []] },
          { $first: "$questions.refValue.displayLabel" },
          "$questions.value"
        ]
      }
    }
  },
  { $unset: "questions.refValue" },
  {
    $group: {
      _id: "$_id",
      status: { $first: "$status" },
      questions: { $push: "$questions" }
    }
  }
])

Playground


第二个选项,您可以使用下面的方法而不使用 $unwind$group 阶段,

  • $project 显示必填字段
  • $type 获取 value
  • 的数据类型
  • $filter 迭代 questions 的循环并通过 type 过滤到 select 只有具有“objectId”元素的值
  • $filter 迭代 questions 的循环并通过 type 过滤到 select 只有 none “obejctId” 元素
  • $lookup 与管道,let 传递参考值并检查 $in 条件,以及 return _idvalue 字段
  • $addFields 使用 $map$filter$mergeObjects
  • 将当前问题与查找结果问题值连接起来
  • $unset 删除不需要的字段
  • $concatArrays 将引用数组和非引用数组合并为一个
db.products.aggregate([
  {
    $project: {
      status: 1,
      ref: {
        $filter: {
          input: "$questions",
          cond: { $eq: [{ $type: "$$this.value" }, "objectId"] }
        }
      },
      nonRef: {
        $filter: {
          input: "$questions",
          cond: { $ne: [{ $type: "$$this.value" }, "objectId"] }
        }
      }
    }
  },
  {
    $lookup: {
      from: "ex_ref_data",
      let: { questionValue: "$ref.value" },
      pipeline: [
        { $match: { $expr: { $in: ["$_id", "$$questionValue"] } } },
        { $project: { value: "$displayLabel" } }
      ],
      as: "ref"
    }
  },
  {
    $addFields: {
      ref: {
        $map: {
          input: "$ref",
          as: "r",
          in: {
            $mergeObjects: [
              "$$r",
              {
                $first: {
                  $filter: {
                    input: "$refResult",
                    cond: { $eq: ["$$this._id", "$$r.value"] }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  { $unset: "ref._id" },
  {
    $project: {
      status: 1,
      questions: { $concatArrays: ["$nonRef", "$ref"] }
    }
  }
])

Playground