I am using the MongoDB Java client to query data:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.5.0</version>
</dependency>
The server version is 3.4.10.
When using the MongoDB shell, I can successfully query using:
db.c1.find(
{ title: { $in: [/test/,/demo/] } },
{ title:1 }
)
But when using the Java driver it does not work. For example:
List<String> keywords = new ArrayList<>();
keywords.add("/test/");
keywords.add("/demo/");
Document titleRegEx = new Document("$in", keywords);
Document filter = new Document("title", titleRegEx);
Document firstDoc = coll.find(filter).first();
logger.info("firstDoc: {}", firstDoc);
Please help me out.
If you profile the MongoDB calls you'll see that this 'find statement' ...
List<String> keywords = new ArrayList<>();
keywords.add("/test/");
keywords.add("/demo/");
Document titleRegEx = new Document("$in", keywords);
Document filter = new Document("title", titleRegEx);
Document firstDoc = coll.find(filter).first();
... causes the following filter to be submitted to MongoDB:
filter: { title: { $in: [ "/test/", "/demo/" ] } } }
Note the value of the $in
document; instead of $in: [/test/,/demo/]
it is: $in: [ "/test/", "/demo/" ]
. So, it is performing exact string matches on "/test/" and "/demo/" rather than regex matches. This explains why this 'find statement' returns nothing.
You engage a regex search when using the Java driver like so:
Filters.regex("title", "test")
The MongoDB Java driver does not allow you to supply a collection of Bson
instances for $in
so if you want to search for documents which match one of the elements in this 'in' list: /test/, /demo/
then you have to form an OR
query. For example:
Bson filter = Filters.or(Filters.regex("title", "test"), Filters.regex("title", "demo"));
FindIterable<Document> documents = collection.find(filter);
If you profile the MongoDB calls you'll see that the above code causes the following 'find statement' to be executed on MongoDB:
find { find: "posts", filter: { $or: [ { title: /test/ }, { title: /demo/ } ] } }
This is functionally equivalent to the command you showed in your question.