2

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

我正在尝试仅对questions.valueObjectId 类型的对象执行查找。并希望从查询中返回如下所示:

[
  {
    "_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"
      }
    ]
  }
]

我将如何重新添加非“查找”值?

谢谢!

4

2 回答 2

1

您需要更正查询的内容,

  • $unwind- 照原样
  • $lookup- 按原样放置,但将as字段重命名为refValue
  • $addFields检查条件是否结果为空数组,然后保持相同的值,否则使用$first运算符替换为查找值
  • $unsetrefValue现在不需要删除它
  • $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" }
    }
  }
])

操场


第二个选项,您可以在没有$unwind$group阶段的情况下使用以下方法,

  • $project显示必填字段
  • $type获取数据类型value
  • $filter迭代循环questions并过滤type以仅选择具有“objectId”元素的值
  • $filter迭代循环questions并过滤type以仅选择无“obejctId”元素
  • $lookup使用管道,let传递参考值和检查$in条件,并返回_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"] }
    }
  }
])

操场

于 2021-06-28T17:42:30.853 回答
0

在您的查询中,问题与$unwind您删除空数组值有关。您需要稍微更新一下查询$ifNull以保留初始数组中的值,但一般来说,您需要使用preserveNullAndEmptyArrays

...
  {
    $project: {
      "questions.id": 1,
      "questions.value": "$questions.value.displayLabel"
    }
  },
  {
    $unwind: {
      path: "$questions.value",
      preserveNullAndEmptyArrays: true
    }
  },
于 2021-06-28T17:33:25.640 回答