Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add to an existing MongoDB Bson Filter in Java

I'm using MongoDB 3.6.3 and the 3.6.0 Mongo & Bson drivers for Java.

Given the following filter:

import static com.mongodb.client.model.Filter.and;
import static com.mongodb.client.model.Filter.eq;
import static com.mongodb.client.model.Filter.gt;
.
.
.
   Bson filter = and(eq("field1", value),
                     gt("field2", value2));

I need to conditionally add another field to filter, effectively making it:

   Bson filter = and(eq("field1", value),
                     gt("field2", value2),
                     eq("field3", optionalValue));

Is there a way to do this by appending that field to filter, or do I have to create the filters separately? eg.

   Bson filter;
   if (optionFieldRequired)
   {
      Bson filter = and(eq("field1", value),
                        gt("field2", value2));
   }
   else
   {
      Bson filter = and(eq("field1", value),
                        gt("field2", value2),
                        eq("field3", optionalValue));
   }
like image 225
Spuggiehawk Avatar asked Apr 17 '18 10:04

Spuggiehawk


People also ask

How do you write a BSON filter?

Bson filter = and(eq("field1", value), gt("field2", value2)); I need to conditionally add another field to filter, effectively making it: Bson filter = and(eq("field1", value), gt("field2", value2), eq("field3", optionalValue));

What is BSON filter?

static Bson. elemMatch(String fieldName, Bson filter) Creates a filter that matches all documents containing a field that is an array where at least one member of the array matches the given filter. static <TItem> Bson. eq(String fieldName, TItem value)

What is BasicDBObject?

BasicDBObject(java.util.Map map) Creates an object from a map. BasicDBObject(java.lang.String key, java.lang.Object value) Creates an object with the given key/value.


1 Answers

Filters.and() returns an instance of the private static class: Filters.AndFilter. There is no public method on AndFilter allowing you to change its state. So, if you want to append an additional filter after constructing this object you'll have to convert it into some other, mutable, form. For example; a BsonDocument.

The following code creates two BsonDocument instances, one by adding a filter to an existing set of filters and the other by creating all three filters at once. Both of these BsonDocument instances are identical and can be used in collection.find():

Bson filter = and(eq("field1", "value"), gt("field2", "value2"));
BsonDocument bsonDocument = filter.toBsonDocument(BsonDocument.class, MongoClient.getDefaultCodecRegistry());

Bson optionalFilter = eq("field3", "optionalValue");
BsonDocument optionalBsonDocument = optionalFilter.toBsonDocument(BsonDocument.class, MongoClient.getDefaultCodecRegistry());

// now add the optional filter to the BsonDocument representation of the original filter
bsonDocument.append("field3", optionalBsonDocument.get("field3"));

Bson completeFilter = and(eq("field1", "value"), gt("field2", "value2"), eq("field3", "optionalValue"));
BsonDocument completeBsonDocument = completeFilter.toBsonDocument(BsonDocument.class, MongoClientSettings.getDefaultCodecRegistry());

assertThat(completeBsonDocument, is(bsonDocument));

So, this solution is functional but I think it's harder to understand and less standard than wrapping the create call in a conditional block, like in your question ...

Bson filter;
if (!optionFieldRequired) {
  filter = and(eq("field1", value),
                    gt("field2", value2));
} else {
  filter = and(eq("field1", value),
                    gt("field2", value2),
                    eq("field3", optionalValue));
}
like image 171
glytching Avatar answered Sep 24 '22 20:09

glytching