Как обновить поле элемента вложенных массивов в MongoDB - PullRequest
0 голосов
/ 12 июня 2019

У меня есть документ, как показано ниже, и я хочу обновить поле, скажем RSSI, точки доступа с указанным MAC-адресом и указанным fingerId. В настоящее время я добиваюсь этого, сначала находя индекс точки доступа, а затем обновляю ее поле. Есть ли лучший способ?

вот образец документа

"_id" : ObjectId("5d00d45bef388e16b9406b13"), 
    "x" : 7.2, 
    "y" : 4.5, 
    "visitTime" : NumberLong(1560337948058), 
    "gridNumber" : NumberInt(-1), 
    "fingerprints" : [
        {
            "accessPoints" : [
                {
                    "MAC" : "MAC5", 
                    "SSID" : "SSID3", 
                    "RSSI" : NumberInt(20)
                }, 
                {
                    "MAC" : "MAC6", 
                    "RSSI" : NumberInt(20)
                }
            ], 
            "orientation" : NumberInt(0), 
            "fingerId" : NumberInt(0)
        }
    ], 

и вот что я сейчас делаю:

 Query query = new Query(new Criteria().andOperator(
                Criteria.where(Fields._ID).is(new BsonObjectId(new ObjectId(obsId))),
                Criteria.where("fingerprints").elemMatch(Criteria.where("fingerId").is(fingerDoc.getId())),
                Criteria.where("fingerprints.accessPoints").elemMatch(Criteria.where("MAC").is(mac))

        ));

        int index = getIndexOfAP(collection,obsId, mac);

        if(index != -1) {
            Update update = new Update().set("fingerprints.$.accessPoints." + index + ".RSSI", newValue.getRSSI());
            UpdateResult updateResult = mongoTemplate.updateMulti(query, update, collection);
        }

Я также пытался использовать fingerprints.$.accessPoints.$.RSSI, и я получаю too many $ error любые альтернативные решения для использования нескольких $, кроме перепроектирования БД, будет приветствоваться.

  • Обратите внимание, что здесь есть только один отпечаток, но в реальных данных их будет много.

1 Ответ

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

Вот решение, которое я придумал, учитывая тот факт, что MAC уникален в моем случае:

  BsonDocument bsonDocument = new BsonDocument();
        bsonDocument.append(Fields._ID,new BsonObjectId(new ObjectId(obsId)));
        bsonDocument.append("fingerprints.fingerId",new BsonInt32(fingerprintDoc.getFingerId()));


        mongoTemplate.getCollection(collection).updateMany(bsonDocument,
                new Document().append("$set", new Document().append("fingerprints.$.accessPoints.$[item].RSSI", newValue.getRSSI())),
                new UpdateOptions()
                        .arrayFilters(
                                Collections.singletonList( Filters.in("item.MAC",
                                        Collections.singletonList(mac)) ))
        );

таким образом, я сначала нахожу нужный отпечаток пальца с заданным идентификатором и обновляю RSSI точки доступа, которая соответствует mac, и это то, что я искал

...