对象结构(仅作为示例,一个对象中有数千个回调):
{
"_id" : ObjectId("5ce82dd1eed5a17f33ec025a"),
"id" : "AAA",
"pac" : "",
"callbacks" : [
{
"_id" : ObjectId("5ce82e29eed5a17f33ec0287"),
"timestamp" : 1558720040,
"type" : "data_bidir",
"seqNumber" : 49,
"messages" : [
{
"isCode" : true,
"_id" : ObjectId("5ce82e29eed5a17f33ec0294"),
"key" : "action",
"value" : "extra_long_press"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e29eed5a17f33ec0293"),
"key" : "version",
"value" : "6"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e29eed5a17f33ec0292"),
"key" : "firmware",
"value" : "0.45"
}
],
"created" : ISODate("2019-05-24T17:47:21.476Z")
},
{
"_id" : ObjectId("5ce82e42eed5a17f33ec0295"),
"timestamp" : 1558720040,
"type" : "service_geoloc",
"seqNumber" : 49,
"messages" : [
{
"isCode" : true,
"_id" : ObjectId("5ce82e42eed5a17f33ec029b"),
"key" : "lqi",
"value" : "Good"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e42eed5a17f33ec029a"),
"key" : "latitude",
"value" : "50.67593721530616"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e42eed5a17f33ec0299"),
"key" : "longitude",
"value" : "14.03118116624828"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e42eed5a17f33ec0298"),
"key" : "radius",
"value" : "8514"
},
{
"isCode" : true,
"_id" : ObjectId("5ce82e42eed5a17f33ec0297"),
"key" : "da_source",
"value" : "2"
},
{
"isCode" : true,
"_id" : ObjectId("5ce82e42eed5a17f33ec0296"),
"key" : "da_status",
"value" : "1"
}
],
"created" : ISODate("2019-05-24T17:47:46.547Z")
}
]
}
仅当a)callbacks.type为“ service_geoloc”和b)如果消息包含key = da_source和value = 2(在示例数据中,第二个回调将受到影响)时,我才需要将对象推送到所有消息。
条件a)可以通过arrayFilters轻松管理:
db.getCollection("devices").updateMany(
{ id: 'AAA'},
{ $push: {
"callbacks.$[c].messages" : {
$each: [{key: "action", value: "atlas_position_network", isCode: true}],
$position: 0
}
}
},
{ arrayFilters: [{"c.type": "service_geoloc"}], multi: true}
)
但是我不知道如何应用条件b)。我还尝试了elemMatch-它在两种情况下均可工作,但仅更新了一条消息。
答案 0 :(得分:0)
我能够分两步完成。也许使用shell一步不可能做到这一点。
步骤1 =将项目推入具有常规值的message数组中
db.getCollection("devices").updateMany(
{ id: 'AAA'},
{ $push: {
"callbacks.$[c].messages" : {
$each: [{key: "action", value: "atlas_position_network", isCode: true}],
$position: 0
}
}
},
{ arrayFilters: [{"c.type": "service_geoloc"}], multi: true}
)
步骤2 =根据固定位置上的其他项目更新值:
db.getCollection('devices').updateMany(
{ id: 'AAA' },
{ $set: { "callbacks.$[c].messages.0.value": "atlas_position_wifi"} },
{ arrayFilters: [{ "c.type": "service_geoloc", "c.messages.5.value": "6", "c.messages.5.key": "da_source" }], multi: true }
)