Skip to content

Commit 777faa1

Browse files
committed
Support DBRef documents in Filters.not
JAVA-2877
1 parent dc3c177 commit 777faa1

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,16 @@
3434
import org.bson.conversions.Bson;
3535

3636
import java.util.Arrays;
37+
import java.util.HashSet;
3738
import java.util.List;
3839
import java.util.Map;
40+
import java.util.Set;
3941
import java.util.regex.Pattern;
4042

4143
import static com.mongodb.assertions.Assertions.notNull;
4244
import static com.mongodb.client.model.BuildersHelper.encodeValue;
4345
import static java.util.Arrays.asList;
46+
import static java.util.Collections.unmodifiableSet;
4447

4548
/**
4649
* A factory for query filters. A convenient way to use this class is to statically import all of its methods, which allows usage like:
@@ -1119,6 +1122,8 @@ public String toString() {
11191122
}
11201123

11211124
private static class NotFilter implements Bson {
1125+
private static final Set<String> DBREF_KEYS = unmodifiableSet(new HashSet<String>(asList("$ref", "$id")));
1126+
private static final Set<String> DBREF_KEYS_WITH_DB = unmodifiableSet(new HashSet<String>(asList("$ref", "$id", "$db")));
11221127
private final Bson filter;
11231128

11241129
NotFilter(final Bson filter) {
@@ -1140,10 +1145,25 @@ public <TDocument> BsonDocument toBsonDocument(final Class<TDocument> documentCl
11401145
}
11411146
}
11421147

1148+
private boolean containsOperator(final BsonDocument value) {
1149+
Set<String> keys = value.keySet();
1150+
if (keys.equals(DBREF_KEYS) || keys.equals(DBREF_KEYS_WITH_DB)) {
1151+
return false;
1152+
}
1153+
1154+
for (String key : keys) {
1155+
if (key.startsWith("$")) {
1156+
return true;
1157+
}
1158+
}
1159+
1160+
return false;
1161+
}
1162+
11431163
private BsonDocument createFilter(final String fieldName, final BsonValue value) {
11441164
if (fieldName.startsWith("$")) {
11451165
return new BsonDocument("$not", new BsonDocument(fieldName, value));
1146-
} else if (value.isDocument() || value.isRegularExpression()) {
1166+
} else if ((value.isDocument() && containsOperator(value.asDocument())) || value.isRegularExpression()) {
11471167
return new BsonDocument(fieldName, new BsonDocument("$not", value));
11481168
}
11491169
return new BsonDocument(fieldName, new BsonDocument("$not", new BsonDocument("$eq", value)));

driver-core/src/test/functional/com/mongodb/client/model/FiltersFunctionalSpecification.groovy

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,31 @@ class FiltersFunctionalSpecification extends OperationFunctionalSpecification {
9494
find(not(regex('y', 'a.*'))) == [b, c]
9595

9696
when:
97-
find(not(and(eq('x', 1), eq('x', 1)))) == [b, c]
97+
def dbref = Document.parse('{$ref: "1", $id: "1"}')
98+
def dbrefDoc = new Document('_id', 4).append('dbref', dbref)
99+
getCollectionHelper().insertDocuments(dbrefDoc)
100+
101+
then:
102+
find(not(eq('dbref', dbref))) == [a, b, c]
103+
104+
when:
105+
getCollectionHelper().deleteOne(dbrefDoc)
106+
dbref.put('$db', '1')
107+
dbrefDoc.put('dbref', dbref)
108+
getCollectionHelper().insertDocuments(dbrefDoc)
109+
110+
then:
111+
find(not(eq('dbref', dbref))) == [a, b, c]
112+
113+
when:
114+
def subDoc = Document.parse('{x: 1, b: 1}')
115+
getCollectionHelper().insertDocuments(new Document('subDoc', subDoc))
116+
117+
then:
118+
find(not(eq('subDoc', subDoc))) == [a, b, c, dbrefDoc]
119+
120+
when:
121+
find(not(and(eq('x', 1), eq('x', 1))))
98122

99123
then:
100124
thrown MongoQueryException

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ import static com.mongodb.client.model.Filters.size
7070
import static com.mongodb.client.model.Filters.text
7171
import static com.mongodb.client.model.Filters.type
7272
import static com.mongodb.client.model.Filters.where
73-
import static java.util.Arrays.asList
7473
import static org.bson.BsonDocument.parse
7574
import static org.bson.codecs.configuration.CodecRegistries.fromProviders
7675

@@ -106,7 +105,11 @@ class FiltersSpecification extends Specification {
106105
toBson(not(or(eq('x', 1), eq('x', 2)))) == parse('{$not: {$or: [{x: 1}, {x: 2}]}}')
107106
toBson(not(or(Filters.in('x', 1, 2), eq('x', 3)))) == parse('{$not: {$or: [{x: {$in: [1, 2]}}, {x: 3}]}}')
108107

109-
toBson(not(new BsonDocument('$in', new BsonArray(asList(new BsonInt32(1)))))) == parse('{$not: {$in: [1]}}')
108+
toBson(not(parse('{$in: [1]}'))) == parse('{$not: {$in: [1]}}')
109+
110+
toBson(not(eq('x', parse('{a: 1, b: 1}')))) == parse('{x: {$not: {$eq: {"a": 1, "b": 1}}}}')
111+
toBson(not(eq('x', parse('{$ref: "1", $id: "1"}')))) == parse('{x: {$not: {$eq: {"$ref": "1", "$id": "1"}}}}')
112+
toBson(not(eq('x', parse('{$ref: "1", $id: "1", $db: "db"}')))) == parse('{x: {$not: {$eq: {"$ref": "1", "$id": "1", $db: "db"}}}}')
110113
}
111114

112115
def 'should render $nor'() {

0 commit comments

Comments
 (0)