如何使用Spring + Mongo

时间:2016-02-27 11:56:59

标签: java spring-data spring-mongo

我在MongoDB集合中有这样的文档:

{
  id : ... 
  listA:[{
          id: ...,
          thing:...,
          listB:[{...},{...}]
          },...
            ]
}

(顶级ID是正常的自动生成的MongoDB ID。子文档对象的另一个ID是我单独生成并推入列表的伪ID)

问题:我想(1)添加到listB和(2)更改thing

这个对象可能非常大,并且可能有多个线程可能在对象上运行,因此我想避免findOne,更新,然后save类型的场景。

我想在Spring Data中执行此操作,方法与我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);
}

但是我无法生成正确的查询/标准。

提前致谢。

2 个答案:

答案 0 :(得分:5)

您应该尝试下一个查询:

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");

答案 1 :(得分:3)

我认为你混淆了两个概念:

  • 在原子操作中进行2次更新。
  • 更换整个文件。

我知道您只是想更新而不是因为性能原因而更换,所以接受的答案是正确的。

但是,另一方面, findOne - save 机制完全是线程安全的,因为当整个文档是 save 操作时,两个更新发生了。更换。因此,如果在 findOne save 操作之间存在另一个修改文档的线程,则您的文档将被最新版本正确替换。然后,当然你有一个问题,因为第二次替换的线程不会被通知第一次修改,但你也接受了解决方案的问题。

如果你真的想避免这种情况,你应该考虑a versioning mechanism or checking old data before updating