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.
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: {}
}
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: {}
}