2017-09-27 49 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"使用遊標,如上面鏈接的答案中所述。