向嵌套数组添加新项并根据插入项更新现有元素
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
将新文档替换为旧文档。
{
"_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
将新文档替换为旧文档。