Skip to content

Commit 4d0f5ce

Browse files
committed
Updated Filter.Not
JAVA-1740
1 parent d5fb682 commit 4d0f5ce

File tree

2 files changed

+21
-62
lines changed

2 files changed

+21
-62
lines changed

driver-core/src/main/com/mongodb/client/model/Filters.java

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -689,69 +689,27 @@ public NotFilter(final Bson filter) {
689689

690690
@Override
691691
public <TDocument> BsonDocument toBsonDocument(final Class<TDocument> documentClass, final CodecRegistry codecRegistry) {
692-
BsonDocument bsonFilter = toFilter(filter.toBsonDocument(documentClass, codecRegistry));
693-
if (bsonFilter.keySet().iterator().next().startsWith("$")) {
694-
throw new IllegalArgumentException("Invalid $not document, the filter document must start with the field name that "
695-
+ "the $not operator applies to: " + filter);
696-
}
697-
return bsonFilter;
698-
}
699-
700-
public BsonDocument toFilter(final BsonDocument filterDocument) {
701-
BsonDocument combinedDocument = new BsonDocument();
702-
for (Map.Entry<String, BsonValue> docs : filterDocument.entrySet()) {
703-
combinedDocument = combineDocuments(combinedDocument, createFilter(docs.getKey(), docs.getValue()));
692+
BsonDocument filterDocument = filter.toBsonDocument(documentClass, codecRegistry);
693+
if (filterDocument.size() == 1) {
694+
Map.Entry<String, BsonValue> entry = filterDocument.entrySet().iterator().next();
695+
return createFilter(entry.getKey(), entry.getValue());
696+
} else {
697+
BsonArray values = new BsonArray();
698+
for (Map.Entry<String, BsonValue> docs : filterDocument.entrySet()) {
699+
values.add(new BsonDocument(docs.getKey(), docs.getValue()));
700+
}
701+
return createFilter("$and", values);
704702
}
705-
return combinedDocument;
706703
}
707704

708705
private BsonDocument createFilter(final String fieldName, final BsonValue value) {
709-
if (fieldName.equals("$and")) {
710-
return toFilter(flattenBsonArray(value.asArray()));
711-
} else if (value.isDocument() && ((BsonDocument) value).keySet().iterator().next().startsWith("$")) {
712-
return new BsonDocument(fieldName, new BsonDocument("$not", value));
713-
} else if (value.isRegularExpression()) {
706+
if (fieldName.startsWith("$")) {
707+
return new BsonDocument("$not", new BsonDocument(fieldName, value));
708+
} else if (value.isDocument() || value.isRegularExpression()) {
714709
return new BsonDocument(fieldName, new BsonDocument("$not", value));
715710
}
716711
return new BsonDocument(fieldName, new BsonDocument("$not", new BsonDocument("$eq", value)));
717712
}
718713

719-
private BsonDocument combineDocuments(final BsonDocument document1, final BsonDocument document2) {
720-
BsonDocument combinedDocument = document1;
721-
for (Map.Entry<String, BsonValue> entry : document2.entrySet()) {
722-
String key = entry.getKey();
723-
BsonValue val = entry.getValue();
724-
BsonDocument document = combinedDocument.getDocument(key, new BsonDocument());
725-
if (!val.isDocument()) {
726-
if (document.containsKey("$in")) {
727-
BsonArray inArray = document.getArray("$in");
728-
inArray.add(val);
729-
document.put("$in", inArray);
730-
} else if (document.containsKey("$eq")) {
731-
BsonArray inArray = document.getArray("$in", new BsonArray());
732-
inArray.add(document.remove("$eq"));
733-
inArray.add(val);
734-
document.put("$in", inArray);
735-
} else {
736-
document.put("$eq", val);
737-
}
738-
} else {
739-
document = val.asDocument();
740-
}
741-
combinedDocument.put(key, document);
742-
}
743-
return combinedDocument;
744-
}
745-
746-
private BsonDocument flattenBsonArray(final BsonArray bsonArray) {
747-
BsonDocument combinedDocument = new BsonDocument();
748-
for (BsonValue bsonValue : bsonArray) {
749-
if (!bsonValue.isDocument()) {
750-
throw new IllegalArgumentException("Invalid $not document " + bsonValue);
751-
}
752-
combinedDocument = combineDocuments(combinedDocument, bsonValue.asDocument());
753-
}
754-
return combinedDocument;
755-
}
756714
}
757715
}

driver-core/src/test/unit/com/mongodb/client/model/FiltersSpecification.groovy

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,16 @@ class FiltersSpecification extends Specification {
7272
toBson(not(eq('x', 1))) == parse('{x : {$not: {$eq: 1}}}')
7373
toBson(not(gt('x', 1))) == parse('{x : {$not: {$gt: 1}}}')
7474
toBson(not(regex('x', '^p.*'))) == parse('{x : {$not: /^p.*/}}')
75-
toBson(not(and(gt('x', 1), eq('y', 20)))) == parse('{x : {$not: {$gt: 1}}, y : {$not: {$eq: 20}}}')
76-
toBson(not(and(eq('x', 1), eq('x', 2)))) == parse('{x : {$not: {$in: [1, 2]}}}')
77-
toBson(not(and(Filters.in('x', 1, 2), eq('x', 3)))) == parse('{x : {$not: {$in: [1, 2, 3]}}}')
7875

79-
when: 'Missing a field name it should error'
80-
toBson(not(new BsonDocument('$in', new BsonArray(asList(new BsonInt32(1))))))
76+
toBson(not(and(gt('x', 1), eq('y', 20)))) == parse('{$not: {$and: [{x: {$gt: 1}}, {y: 20}]}}')
77+
toBson(not(and(eq('x', 1), eq('x', 2)))) == parse('{$not: {$and: [{x: 1}, {x: 2}]}}')
78+
toBson(not(and(Filters.in('x', 1, 2), eq('x', 3)))) == parse('{$not: {$and: [{x: {$in: [1, 2]}}, {x: 3}]}}')
8179

82-
then:
83-
thrown(IllegalArgumentException)
80+
toBson(not(or(gt('x', 1), eq('y', 20)))) == parse('{$not: {$or: [{x: {$gt: 1}}, {y: 20}]}}')
81+
toBson(not(or(eq('x', 1), eq('x', 2)))) == parse('{$not: {$or: [{x: 1}, {x: 2}]}}')
82+
toBson(not(or(Filters.in('x', 1, 2), eq('x', 3)))) == parse('{$not: {$or: [{x: {$in: [1, 2]}}, {x: 3}]}}')
83+
84+
toBson(not(new BsonDocument('$in', new BsonArray(asList(new BsonInt32(1)))))) == parse('{$not: {$in: [1]}}')
8485
}
8586

8687
def 'should render $nor'() {

0 commit comments

Comments
 (0)