向嵌套数组添加新项并根据插入项更新现有元素

Add a new item to a nested array and update the existing elements according to the inserted item

{
    "_id": {
        "$oid": "6200c86d083ef16be6dae5b1"
    },
    "type": "Hair_Length",
    "values": [
        {
            "name": "Bald / Clean Shaven",
            "value": "bald",
            "default": "yes"
        },
        {
            "name": "Crew Cut",
            "value": "crewcut"
        },
        {
            "name": "Short",
            "value": "Short"
        },
        {
            "name": "Medium",
            "value": "Medium"
        },
        {
            "name": "Long",
            "value": "Long"
        },
        {
            "name": "Chin Length",
            "value": "ChinLength"
        },
        {
            "name": "Shoulder Length",
            "value": "ShoulderLength"
        },
        {
            "name": "Dreadlocks",
            "value": "Dreadlocks"
        }
    ]
}

大家好!如果我将名称和值作为 json 对象,那么只有在我们得到 "default":"yes" 除了名称和值之外,我才会更新或添加到此文档,那么如果默认为已经存在我希望你得到点

感谢大家 tq

既然你知道你的新项目是否是默认项目,那么在查询之前,最好将查询调整到相关情况再执行。但只是为了挑战,这是一个只有一个查询的解决方案。我建议您将它分成两个查询,并且在每种情况下只使用一个。

db.collection.aggregate([
  {
    $match: {type: "Hair_Length"}
  },
  {
    $addFields: {
      newValue: {"name": "short hair", "value": "shorthair", "default": "yes"},
      values: {$filter: {input: "$values",
          as: "item",
          cond: {$ne: ["$$item.value", "shorthair"]}
        }
      }
    }
  },
  {
    $facet: {
      newIsDefault: [
        {
          $project: {"values.name": 1, "values.value": 1, type: 1, newValue: 1}
        }
      ],
      newIsRegular: [
        {$project: {values: 1, type: 1, newValue: 1}
        }
      ]
    }
  },
  {
    $project: {newIsDefault: {$arrayElemAt: ["$newIsDefault", 0]},
               newIsRegular: {$arrayElemAt: ["$newIsRegular", 0]}}
  },
  {
    $replaceRoot: {
      newRoot: {
        $cond: [{$eq: ["$newIsDefault.newValue.default", "yes"]},
          "$newIsDefault",
          "$newIsRegular"
        ]
      }
    }
  },
  {
    $project: {
      values: {$setUnion: [["$newValue"], "$values"]},
      type: 1
    }
  },
  {$merge: {into: "collection"}}
])

您可以在 one case and on another case 的操场上看到它的效果。

大意主要有两种情况:新项目是否默认。在这两种情况下,您首先从列表中过滤出具有值的元素与新项目匹配(如果它们存在)。然后,如果新项目是默认的,则从列表中的项目中删除默认字段。只有现在我们才能将新项目插入到列表中。

查询: 首先,您使用 $addFields 添加新项目,如果存在,则使用 $filter 来添加新项目,然后使用 $facet 为这两种情况创建文档。其中之一是新项目是默认的情况,而 e 是不是的情况。然后使用 $cond 选择要使用的项目,然后使用 $setUnion 将新项目添加到其中。最后一步是 $merge 将新文档替换为旧文档。