首页 > 解决方案 > 如何更新 MongoDB 中嵌套数组元素的字段

问题描述

我有一个像下面这样的文档,我想更新一个具有给定 MAC 和给定 fingerId 的 accessPoint 的字段,比如 RSSI。目前我正在通过首先找到 accessPoint 的索引然后更新它的字段来实现这一点。有没有更好的方法?

这是一个示例文档

"_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

标签: mongodbspring-data-mongodbmongotemplate

解决方案


考虑到 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)) ))
        );

通过这种方式,我首先使用给定的 Id 找到所需的指纹并更新与 mac 匹配的 accessPoint 的 RSSI,这就是我正在寻找的


推荐阅读