Search code examples
mongodbspring-data-mongodb

How do I delete productData in products collection given a list of product ids


I have a document which has a field that I want to delete given a list of ids. Here is one of the objects in the collection named products: Given a list of productIds delete the productData fields for those productIds. The method signature is like this

//return productIds whose productData field has been deleted
public List<ProductId> deleteProductDataForIds(List<ProductId> productIds);

The productIds are an array similar to that shown below and are represented as a ProductId class and the product JSON is as shown below with additional fields omitted for brevity:

{
"_id" : {
   "productId" : P202,
   "categoryId" : 111
},
"productData" : {
  "description": "Paco Rabane Fragrance",
  "productSku": "11222-RTTTT"
 },
 "productName: "Paco Rabanne",
 "qty": 1222222,
 ... other fields omitted for brevity
}

I want to use Spring Data Mongo, to delete the productData given a list of _id values. For example, given the list of productIds below, delete all the related productData.

[ 
   {
    "_id": {
         "productId": 112, 
         "category" : "444""
      },

   "_id": {
     "productId": 132, 
     "category" : "445""
   }
]

I put together some code to attempt the deletion, but I'm stuck with how to add the delete portion.

var productId = new ProductId(1122, 122);

BulkOperations bulkOps =  mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED,

Product.class,  "products");

List<Pair<Query, Update>> updates = new ArrayList<>();

// This is not where I'm stuck adding code to delete productData 

 products.forEach(product -> updates.add(Pair.of(where("productId", 
            product.getProductId()),set(product))));

log.info("Writing to database {} ",updates );

}
      
   //Helper method for add clause
   private static Query where(String field, Object value) {
      return new Query().addCriteria(Criteria.where(field).is(value));
   }

I'm not sure the updateMulti can be used. I'm able to use it to update the products, but unsure how to delete the productData for a list of product ids.


Solution

  • You need to use MongoTemplate.remove(...) method:

    Note: It returns DeleteResult which allows you verify deleted documents (DeleteResult.getDeletedCount())

    public DeleteResult deleteProductDataForIds(List<ProductId> productIds) {
        Query query = Query.criteria(Criteria.where("_id").in(productIds));
        return mongoTemplate.remove(query, Product.class);
        //Query: { "_id" : { "$in" : [ { "$java" : ProductId@6d969330 }, { "$java" : ProductId@4861cca9 } ] } }, Fields: {}, Sort: {}
    }
    

    Alternative

    You can use Criteria.orOperator operator and remove by key pairs.

    public DeleteResult deleteProductDataForIds(List<ProductId> productIds) {
        Query query = Query.query(new Criteria().orOperator(productIds.stream()
                .map(p -> Criteria.where("_id.productId").is(p.getProductId()).and("_id.categoryId").is(p.getCategoryId()))
                .collect(Collectors.toList()))
        );
        return mongoTemplate.remove(query, Product.class);
        //Query: { "$or" : [{ "_id.productId" : 112, "_id.categoryId" : "445"}, { "_id.productId" : 132, "_id.categoryId" : "444"}]}, Fields: {}, Sort: {}
    }