如何在 MongoDB 中更新嵌套数组元素的字段

How to update a field of an element of nested Arrays in 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 除了重新设计数据库之外,任何使用多个 $ 的替代解决方案,我们将不胜感激。

考虑到 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,这就是我要找的东西