Нажмите для массива на основе других атрибутов - PullRequest
0 голосов
/ 30 июня 2019

Структура объекта (только пример, в одном объекте тысячи обратных вызовов):

{
    "_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)если сообщения содержат ключ = da_source и значение = 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 - он работал с обоими условиями, но обновил только одно сообщение.

1 Ответ

0 голосов
/ 30 июня 2019

Мне удалось сделать это в 2 этапа.Может быть, это невозможно сделать за один шаг с помощью оболочки.

Шаг 1 = вставить элемент в массив сообщений с общим значением:

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 }
)
...