我有一个包含以下格式的文档的集合
{
name: "A",
details : {
matchA: {
comment: "Hello",
score: 5
},
matchI: {
score: 10
},
lastMatch:{
score: 5
}
}
},
{
name: "B",
details : {
match2: {
score: 5
},
match7: {
score: 10
},
firstMatch:{
score: 5
}
}
}
我不能立即知道作为细节的孩子的钥匙的名称,他们不遵循已知的格式,可以有不同的数量等。
我想编写一个查询来更新子项,使得得分小于5的子文档会添加一个新字段(比如lowScore:true)。
我已经看了一下,我发现了$和$ elemMatch,但那些只适用于阵列。是否有相应的子文档?有没有办法使用聚合管道呢?
答案 0 :(得分:1)
我认为你不能使用正常update()
来做到这一点。聚合框架有一种方法,但它本身不能改变任何持久化数据。因此,您需要循环查看结果并单独更新文档,例如在这里:Aggregation with update in mongoDB
这是将您的数据转换为后续更新所需内容所需的查询:
collection.aggregate({
$addFields: {
"details": {
$objectToArray: "$details" // transform "details" into uniform array of key-value pairs
}
}
}, {
$unwind: "$details" // flatten the array created above
}, {
$match: {
"details.v.score": {
$lt: 10 // filter out anything that's not relevant to us
// (please note that I used some other filter than the one you wanted "score less than 5" to get some results using your sample data
},
"details.v.lowScore": { // this filter is not really required but it seems to make sense to check for the presence of the field that you want to create in case you run the query repeatedly
$exists: false
}
}
}, {
$project: {
"fieldsToUpdate": "$details.k" // ...by populating the "details" array again
}
})
运行此查询将返回:
/* 1 */
{
"_id" : ObjectId("59cc0b6afab2f8c9e1404641"),
"fieldsToUpdate" : "matchA"
}
/* 2 */
{
"_id" : ObjectId("59cc0b6afab2f8c9e1404641"),
"fieldsToUpdate" : "lastMatch"
}
/* 3 */
{
"_id" : ObjectId("59cc0b6afab2f8c9e1404643"),
"fieldsToUpdate" : "match2"
}
/* 4 */
{
"_id" : ObjectId("59cc0b6afab2f8c9e1404643"),
"fieldsToUpdate" : "firstMatch"
}
然后,您可以使用上述链接答案中所述的光标$set
您的新字段"lowScore"
。