5

我最近花了一些时间尝试$pull通过 Spring 的 Data MongoOperations 界面使用该运算符,所以我认为如果有人遇到类似问题,分享我的发现会很好。

所以这里...

我有 2 个类似的 java POJO:

@Document
public class OutterObject{

    private String id;
    private String name;
    private List<InnerDocument> innerDocs;


    //SETTERS - GETTERS Ommited


public class InnerDocument{


    private String id;
    private String name;

         //SETTERS - GETTERS Ommited

这存储在 Mongo 集合中,如下所示:

 "_id" : "doc2",
 "_class" : "OutterObject",
 "name" : "doc2",
 "innerDocs" : [{
      "_id" : "innerDoc21",
      "name" : "innerDoc21"
  }, {
      "_id" : "innerDoc22",
      "name" : "innerDoc22"
  }]

我正在尝试使用 $pull 运算符来删除 innerDoc 集合中具有名称值 =“innerDoc22”的所有对象。

我知道如何使用 mongo 驱动程序来完成此任务,如下所示:

 List<String> ids = 
         Arrays.asList("innerDoc22");

 BasicDBObject find = new BasicDBObject();

 match.put("innerDocs.name", 
           BasicDBObjectBuilder.start("$in", ids).get());

    BasicDBObject update = new BasicDBObject();
        update.put(
                "$pull",
                BasicDBObjectBuilder.start("innerDocs",
                        BasicDBObjectBuilder.start("name", "innerDoc22").get()).get());

  DBCollection col= mongoOperations.getDb().getCollection("outterObject");

  col.update(find , update);

我正在尝试使用 Spring 的 MongoOperations 接口来完成同样的事情。这是我使用 MongoOperations 接口的代码:

List<String> ids = Arrays.asList("innerDoc22");

Query removeQuery = Query.query(Criteria.where("innerDocs.name").in(ids));

WriteResult wc = mongoOperations.upsert(
                    removeQuery, 
                    new Update().pull("innerDocs.name", "innerDoc22"), 
                    OutterObject.class);
System.out.println(wc.getLastError());

调用更新时我没有收到任何错误,getLastError()根本没有在数据库中完成。

我知道这里已经提出了类似的问题,但给出的答案不使用 MongoOperations 界面。

4

7 回答 7

5

经过一番搜索并查看源代码后,我意识到我需要将 InnerDocument 对象作为第二个参数传递给 pull 方法,以便 spring 类能够正确地进行映射。

事实证明,我可以在选择对象时导航对象(我在 removeQuery 中使用“innerDocs.name”),但在更新文档时我不能(或没有找到方法)做同样的事情。

下面是我如何使用 MongoOperations 实现查询:

List<String> ids = Arrays.asList("innerDoc22", "innerDoc21");

Query removeQuery = Query.query(Criteria.where("innerDocs.name").in(ids));

WriteResult wc = 
       mongoOperations.upsert(removeQuery, 
           new Update().pull("innerDocs", 
           new InnerDocument("innerDoc22", null)), 
           OutterObject.class);

System.out.println(wc.getLastError());
于 2012-08-21T11:46:08.437 回答
2

您也可以使用 BasicDBObject 而不是我偶然发现的 InnerDocument。通过打印更新对象,可以看到实际的mongo shell查询json,对调试非常有帮助。:

Update updateObj = new Update()
         .pull("innerDocs", new BasicDBObject("innerDocs.name","innerDoc22"));

System.out.println("UPDATE OBJ: " + updateObj.toString());

结果是:

UPDATE OBJ: { "$pull" : { "innerDocs" : { "innerDocs.name" : "innerDoc22"}}}

于 2016-05-20T11:40:12.270 回答
2

我尝试了 med116 给出的解决方案,我不得不修改它才能工作:

Update updateObj = new Update().pull("innerDocs", new BasicDBObject("name","innerDoc22"));

因为否则我的数组中没有匹配的对象。

于 2018-10-30T07:51:42.740 回答
0

如果您只是想从没有任何其他属性(如名称)的数组中删除一个元素,请编写您希望的查询并

Update update = new Update();
update.pull("Yourarrayname","valueyouwishtodelete");  
mongoTemplate.upsert(query,update,"collectionname");
于 2021-04-27T18:25:39.660 回答
0

在 spring data mongo 中,就像这样:


//remove array's one elem
UpdateResult wc = mongoTemplate.upsert(removeQuery,new Update().pull("tags",Query.query(Criteria.where("tag").is("java"))),TestPull.class);
//remove array's multi-elem
UpdateResult wc1 = mongoTemplate.upsert(removeQuery,new Update().pull("tags",Query.query(Criteria.where("tag").in(Arrays.asList("mongo", "netty")))),TestPull.class);
于 2018-12-30T09:13:44.063 回答
0

这对我有用!

UpdateResult updateResult = mongoTemplate.updateMulti(new Query(where("id").is(activity.getId())), new Update().pull("comments", new Query(where("id").is(commentId))), Activity.class);

它将生成:

Calling update using query: { "_id" : { "$oid" : "61f900e7c7b79442eb3855ea"}} and update: { "$pull" : { "comments" : { "_id" : "61fac32e3f9ab5646e016bc8"}}} in collection: activity
于 2022-02-02T18:23:29.863 回答
0

这就是我的解决方案 - 感谢@ufasoli:

  public Mono<ProjectChild> DeleteCritTemplChild(String id, String idch) {
    Query query = new Query();
    query.addCriteria(Criteria
                           .where("_id")
                           .is(id)
                           .and("tasks._id")
                           .is(idch)
                     );

    Update update = new Update();
    update.set("tasks.$", null);

    return template
         // findAndModify:
         // Find/modify/get the "new object" from a single operation.
         .findAndModify(
              query, update,
              new FindAndModifyOptions().returnNew(true), ProjectChild.class
                       );
  }
于 2021-12-23T21:12:30.160 回答