MongoDB & Spring Data remove Elements from Arrays

In this blogpost I will be showing how to execute a Mongo Query using Spring Data in order to "pull" multiple items in a object's collection. The model :

@Document(collection="Book")
 public class Book{

      private String ISBN;
      private String bookTitle;
      private List< String > categories;


  //SETTERS - GETTERS
  }

  public class Category{
    
      private String categoryId;
      private String categoryName;
   }

A typical Mongo Document would be something like :

   {
      "isbn" : "11111111", 
      "bookTitle" : "My Book Title", 
      "categories" :[
          {
            "categoryId" : "cat1",
            "categoryName": "My Category 1"
          },
          {
            "categoryId" : "cat2",
            "categoryName": "My Category 2"
          }
        ]
     }

    {
      "isbn" : "22222222222", 
      "bookTitle" : "My Book Title2", 
      "categories" :[
          {
            "categoryId" : "cat1",
            "categoryName": "My Category 1"
          },
          {
            "categoryId" : "cat3",
            "categoryName": "My Category 3"
          }
        ]
     }

     {
      "isbn" : "333333333", 
      "bookTitle" : "My Book Title3", 
      "categories" :[
          {
            "categoryId" : "cat2",
            "categoryName": "My Category 2"
          },
          {
            "categoryId" : "cat3",
            "categoryName": "My Category 3"
          }
        ]
     }


Now let's assume that cat1 and cat2 are no longer valid. It would be nice if we could remove these categories from all the books in one mongo update query. Here is how to do it using Spring Data.

@Component
public class MyDAO{
   
   // Mongo template injected through Spring

   @Autowired
   private MongoOperations mongoTemplate;

    public void deleteCategories(String[] categories){
     
      //find query
      // find all the programs containing the the categories passed as parameter
      Query findQuery = 
       Query.query(Criteria.where("categories.categoryId").in(Arrays.asList(categories)));      


       // build the Update
        DBObject pullUpdate = 
            BasicDBObjectBuilder.start().add(
               "categoryId",
                      BasicDBObjectBuilder.start()
                                              .add("$in",
                            categories).get()).get();
    
      Update update = new Update().pull("categories", pullUpdate );
     

     // execute the update
      template.updateMulti(findQuery, update, Book.class);

   }

}



    public class SpringDataDemo{
      
       public static void main(String[] args){

             ClassPathXmlApplicationContext context = 
                  new ClassPathXmlApplicationContext("classpath:spring-beans.xml");
             MyDAO myDao = context.getBean("myDao");
             //delete categories "cat1" and "cat2"
             mydao.deleteCategories(new String[]{"cat1", "cat2"});
       
       }
    }


Now the categories cat1 and cat2 will be removed from all the books in the collection.

11 comments:

  1. What is broadcasts.broadcastId

    ReplyDelete
    Replies
    1. It's actually a typo from when I first started writing the article.
      It should be 'categories.categoryId'; its corrected now thanks for pointing it out.

      Delete
  2. Thanx dude for your post.

    ReplyDelete
  3. great, example, any idea of how to update one field value in the array, I have tried that and could not get spring data to work- only a native query.

    ReplyDelete
  4. // execute the update
    template.updateMulti(findQuery, pullUpdate, Book.class);

    should we use 'update' variable, instead of pullUpdate?
    If not, why we introduce it?

    ReplyDelete
    Replies
    1. Hi thanks for pointing this out, it's actually a typo.. you should use the update variable and not the pullUpdate (I've corrected it now).

      Delete
    2. Any idea to update an array field.

      Delete
    3. Hi, what do you mean by update array field? you want to change the value of for example categoryName ?

      Delete
  5. In java class you have a list of strings and in Mongo's document there is array of category objects. Should that be edited?

    ReplyDelete
  6. Tks for share, I was looking for this code a long time

    ReplyDelete