2017-09-27 87 views
0

我有具有以下格式不知道键查询和更新子文档

{ 
    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:真正)。

我环顾了一下,发现$和$ elemMatch,但那些只适用于数组。是否有相同的子文档?有没有使用聚合管道的方法?

回答

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"使用游标,如上面链接的答案中所述。