如何在 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,这就是我要找的东西
我有一个如下所示的文档,我想用给定的 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,这就是我要找的东西