如何使用 Spring+Mongo 更新和添加到子文档列表
How to update and add to subdocument list with Spring+Mongo
我在 MongoDB collection:
中有这样的文档
{
id : ...
listA:[{
id: ...,
thing:...,
listB:[{...},{...}]
},...
]
}
(顶级ID是正常的auto-generated MongoDB ID。子文档的另一个ID object是我单独生成的pseudo-ID并且推入列表)
问题: 我想 (1) 添加到 listB
和 (2) 更改 thing
这个 object 可能相当大,并且可能有多个线程在 object 上运行,所以我想避免 findOne
,更新,然后 save
场景类型。
我想在 Spring 数据中以类似于我推送到 listA
的方式执行此操作,即
@Autowired
private MongoOperations operations;
public void addStuff(String id, Stuff stuff) {
operations.updateFirst(Query.query(Criteria.where("_id").is(id)),
new Update().addToSet("listA", stuff), Stuffs.class);
}
但是我无法生成正确的 Query/Criteria。
提前致谢。
您应该尝试下一个查询:
final Query query = new Query(new Criteria().andOperator(
Criteria.where("_id").is("id"),
Criteria.where("listA").elemMatch(Criteria.where("_id").is("id"))
));
final Update update = new Update().addToSet("listA.$.listB", stuff).set("listA.$.thing", "thing");
final WriteResult wr = mongoOperations.updateFirst(query, update, "collectionName");
我认为你混淆了两个概念:
- 在原子操作中进行 2 次更新。
- 正在替换整个文档。
我了解到您出于性能原因只想更新而不是替换,因此接受的答案是正确的。
但是,另一方面,机制 findOne - save 是完全线程安全的,因为两次更新发生在 save 操作,当整个文档被替换时。因此,如果在 findOne 和 save 操作之间有另一个线程修改您的文档,您的文档将被正确替换为最新版本。然后,当然你有一个问题,因为第二个替换的线程不会收到关于第一次修改的通知,但是你也有这个问题与接受的解决方案。
如果你真的想避免这种情况,你应该想到a versioning mechanism or checking old data before updating
我在 MongoDB collection:
中有这样的文档{
id : ...
listA:[{
id: ...,
thing:...,
listB:[{...},{...}]
},...
]
}
(顶级ID是正常的auto-generated MongoDB ID。子文档的另一个ID object是我单独生成的pseudo-ID并且推入列表)
问题: 我想 (1) 添加到 listB
和 (2) 更改 thing
这个 object 可能相当大,并且可能有多个线程在 object 上运行,所以我想避免 findOne
,更新,然后 save
场景类型。
我想在 Spring 数据中以类似于我推送到 listA
的方式执行此操作,即
@Autowired
private MongoOperations operations;
public void addStuff(String id, Stuff stuff) {
operations.updateFirst(Query.query(Criteria.where("_id").is(id)),
new Update().addToSet("listA", stuff), Stuffs.class);
}
但是我无法生成正确的 Query/Criteria。
提前致谢。
您应该尝试下一个查询:
final Query query = new Query(new Criteria().andOperator(
Criteria.where("_id").is("id"),
Criteria.where("listA").elemMatch(Criteria.where("_id").is("id"))
));
final Update update = new Update().addToSet("listA.$.listB", stuff).set("listA.$.thing", "thing");
final WriteResult wr = mongoOperations.updateFirst(query, update, "collectionName");
我认为你混淆了两个概念:
- 在原子操作中进行 2 次更新。
- 正在替换整个文档。
我了解到您出于性能原因只想更新而不是替换,因此接受的答案是正确的。
但是,另一方面,机制 findOne - save 是完全线程安全的,因为两次更新发生在 save 操作,当整个文档被替换时。因此,如果在 findOne 和 save 操作之间有另一个线程修改您的文档,您的文档将被正确替换为最新版本。然后,当然你有一个问题,因为第二个替换的线程不会收到关于第一次修改的通知,但是你也有这个问题与接受的解决方案。
如果你真的想避免这种情况,你应该想到a versioning mechanism or checking old data before updating