如何在Java中向现有的MongoDB Bson过滤器添加内容

8

我正在使用MongoDB 3.6.3版本,以及Java的3.6.0版Mongo和Bson驱动程序。

考虑以下过滤器:

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));

我需要在“filter”中有条件地添加另一个字段,从而使其变为:

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

有没有一种方法,可以通过将该字段附加到过滤器来完成这个操作,还是我必须单独创建过滤器? 例如。
   Bson filter;
   if (optionFieldRequired)
   {
      filter = and(eq("field1", value),
                   gt("field2", value2));
   }
   else
   {
      filter = and(eq("field1", value),
                   gt("field2", value2),
                   eq("field3", optionalValue));
   }

6
您可以使用ArrayList。类似这样:List<Bson> fields = new ArrayList<>(); fields.add(eq("field1", value)); fields.add(gt("field2", value2)); if (optionFieldRequired) { fields.add(eq("field3", optionalValue)); } Bson filter = and(fields); - s7vr
1个回答

9
Filters.and()返回一个私有静态类Filters.AndFilter的实例。在AndFilter上没有公共方法可以修改它的状态。
因此,如果您想在构建此对象之后添加其他过滤器,您需要将其转换为可变形式,例如一个BsonDocument
以下代码创建了两个BsonDocument实例,一个通过向现有过滤器集合中添加过滤器,另一个是同时创建这三个过滤器。这两个BsonDocument实例是相同的,都可以在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));

所以,这个解决方案是可行的,但我认为它比在条件块中包装创建调用(就像你的问题中那样)更难理解并且不太标准...
Bson filter;
if (!optionFieldRequired) {
  filter = and(eq("field1", value),
                    gt("field2", value2));
} else {
  filter = and(eq("field1", value),
                    gt("field2", value2),
                    eq("field3", optionalValue));
}

谢谢。我本以为可能是这样,但如果你问一些问题,你可以在Stack Overflow上获得一些很酷的见解 :-) - Spuggiehawk
3
MongoClient.getDefaultCodecRegistry()已被替换为MongoClientSettings.getDefaultCodecRegistry() - user52028778
这个答案是无效的,append()会在之前的$and子句并行地附加另一个新子句。 - Shu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接