Caio César
Caio César

Reputation: 221

Remove multiple array Entries on Mongo using MongoOperations

I already can execute the desired query on mongoshell, but i need to make the same query using Java and MongoOperations.

I have checked this question, which is very similar, but it only has one condition, as mine has two and uses the $gte and $lt operators. Here's the working mongo Query:

db.getCollection('example').update({"idVar": "desiredValued"}, { $pull: { "listaHoras": {  $gte: ISODate("2016-11-06T05:50:00.000Z"), $lt: ISODate("2016-11-06T06:30:00.000Z")}}})

Sample doc:

"_id" : ObjectId("58221b4610a3c71f1894ce75"),
"idVar" : "56b11259272f5515b05d70bc",
"date" : ISODate("2016-11-06T03:00:00.000Z"),
"listaHoras" : [ 
    ISODate("2016-11-06T05:40:00.000Z"), 
    ISODate("2016-11-06T06:30:00.000Z"), 
    ISODate("2016-11-06T06:40:00.000Z")
    ]

Where i'll have the ISODATE as a Date variable in Java, and the desiredValue as a String variable.

So far, i have i did the following, using the previously mentioned question as example:

BasicDBObject match = new BasicDBObject("idVar", desiredValue); // to match your document
BasicDBObject update = new BasicDBObject("listaHoras", new BasicDBObject("itemID", "1"));
coll.update(match, new BasicDBObject("$pull", update));

But, as you can see, this is NOT equivalent to the desired query. Since the match for the $pull is matching "itemID"with "1". I do not know, nor was i able to find how to properly use the $gte and $lt on the same query. Neither on how to use just one or both of them. I know it CAN be done as seen on the MongoOperatioons API which says:

"update - the update document that contains the updated object or $ operators to manipulate the existing object."

Anyone knows how it can be done? And if the Date type in Java matches the ISODATE on the Mongo?

Upvotes: 0

Views: 578

Answers (2)

s7vr
s7vr

Reputation: 75914

You can try something like below. This will remove the two items from the listaHoras array.

  Query findQuery = new Query();
  Criteria findCriteria =
          Criteria.where("idVar").is("56b11259272f5515b05d70bc");
  findQuery.addCriteria(findCriteria);

  LocalDate startDt = LocalDate.of(2016, 11, 6);
  LocalTime startTm = LocalTime.of(5, 40, 0);

  LocalDate endDt = LocalDate.of(2016, 11, 6);
  LocalTime endTm = LocalTime.of(6, 35, 0);


  Date start = Date.from(LocalDateTime.of(startDt, startTm).toInstant(ZoneOffset.UTC));
  Date end = Date.from(LocalDateTime.of(endDt, endTm).toInstant(ZoneOffset.UTC));

  Query updateQuery = new Query();
  Criteria updateCriteria =
            Criteria.where(null).gte(start).lt(end);
  updateQuery.addCriteria(updateCriteria);
  mongoOperations.updateMulti(findQuery, update, "example");

Upvotes: 1

Caio César
Caio César

Reputation: 221

I managed to find a solution. It is similar to what Veeram posted as a answer but it's slightly different. I simply removed his updateCriteria and used a BasicDBObject in it's place.

Here's how the full code looks:

Query findQuery = new Query();
Criteria findCriteria = Criteria.where("idVar").is(idVar);
findQuery.addCriteria(findCriteria);
Update update = new Update().pull("listaHoras", new BasicDBObject( "$gte", start).append("$lte", end));
mongoOps.updateMulti(findQuery, update, "CollectionName");

Where start and end are Date variables recieved by the method. Also important to note that Mongo uses the UTC as default timezone, so we must properly format the time in order for it to remove the desired values.

Upvotes: 2

Related Questions