6

I recently spent some time trying to use the $pull operator through Spring's Data MongoOperations interface, so I thought it would be nice to share my findings in case anyone bumps into a similar problem.

So here it goes...

I have 2 java POJOs like so :

@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

This is stored in a Mongo collection like so :

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

I'm trying to use the $pull operator in order to remove all objects inside the innerDoc collection having a name value = "innerDoc22".

I know how to accomplish this using the mongo driver like so :

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

I'm trying to accomplish the same thing using Spring's MongoOperations Interface. Here is my code using the MongoOperations interface :

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

I'm not getting any errors when calling getLastError() the update is simply not done in the database.

I know a similar question has already been asked here but the answer that was given does not use the MongoOperations interface.

7 Answers 7

5

After searching a bit and looking at the source code I realized that I needed to pass an InnerDocument object as a second parameter to the pull method so that the spring classes would be able to do the mapping correctly.

As it turns out I can navigate objects while selecting objects (I'm using "innerDocs.name" in the removeQuery) but I cannot (or havent found a way) do the same when updating a document.

Below is how I implemented the query using 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());
Sign up to request clarification or add additional context in comments.

1 Comment

this [stackoverflow.com/a/27153010/234110] worked for me better, since _class was creating an issue in my case.
2

You can also use the BasicDBObject instead of the InnerDocument I found this out by accident. By printing out the update object, you can see the actual mongo shell query json, which is super helpful for debugging. :

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

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

results in:

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

Comments

2

I tried the solution given by med116 and I had to modify it to work :

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

Because otherwise there was no matching object in my array.

1 Comment

yes, changing "innerDocs.name" to "name" works like a charm!
0

in spring data mongo,just like this:


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

Comments

0

If you simply want to remove an element from array which does not have any other property like name then write the query you wish and

Update update = new Update();
update.pull("Yourarrayname","valueyouwishtodelete");  
mongoTemplate.upsert(query,update,"collectionname");

Comments

0

That's my solution - thanks to @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
                       );
  }

Comments

0

This works for me!

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

It will generate:

Calling update using query: { "_id" : { "$oid" : "61f900e7c7b79442eb3855ea"}} and update: { "$pull" : { "comments" : { "_id" : "61fac32e3f9ab5646e016bc8"}}} in collection: activity

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.