Search code examples
javamongodbmongodb-querymongo-java-driver

How to execute queries with both AND and OR clauses in MongoDB with Java?


I want to execute query in MongoDB 3.2 with Java Driver 3.2, which contains both $and and $or clauses at the same time.

With the reference, I tried the following approach:

List<Document> criteria1 = new ArrayList<>();
List<Document> criteria2 = new ArrayList<>();

criteria1.add(new Document("fetchStatus", new Document("$gte", FetchStatus.PROCESSED_NLP.getID())));
criteria1.add(new Document("fetchStatus", new Document("$lte", fetchStatusParam)));
criteria1.add(new Document("episodeID", new Document("$in", episodeIDs)));

criteria2.add(new Document("fetchStatus", new Document("$eq", PROCESSED_FETCH.getID())));
criteria2.add(new Document("isFullTextRet", new Document("$eq", false)));

BasicDBList or = new BasicDBList();
or.add(criteria1);
or.add(criteria2);

DBObject query = new BasicDBObject("$or", or);
ArrayList<Document> results = dbC_Coll.find(query).into(new ArrayList<>());

Where the criteria1 and criteria2 should be connected with $or while within criteria1 clause the $and should be applied.

The problem is that in MongoDB Java Driver 3.2 there is such no method and I get the Cannot resolve method find(com.mongodb.DBObject) error.

How can I compose a query such as (A && B) || (X && Y) in MongoDB Java Driver 3.2?


Solution

  • Personally, I find it far less confusing to construct the object sequences just like U would with a JSON structure to enhance readability. But it's still just Document() wherever you see {} and List wherever you see []:

    Document query = new Document(
        "$or", Arrays.asList(
            // First document in $or
            new Document(
                "fetchStatus", 
                new Document( "$gte", FetchStatus.PROCESSED_NLP.getID() )
                .append("$lte", fetchStatusParam)
            )
            .append("episodeID", new Document( "$in", episodeIDs)),
            // Second document in $or
            new Document("fetchStatus", PROCESSED_FETCH.getID())
            .append("isFullTextRet", false)
        )
    );
    

    Which is basically the same as:

       {
           "$or": [
               {
                   "fetchStatus": { 
                       "$gte": FetchStatus.PROCESS_NLP.getID(),
                       "$lte": fetchStatusParam
                   },
                   "episodeID": { "$in": episodeIDs }
               },
               {
                   "fetchStatus": PROCESSED_FETCH.getID(),
                   "isFullTextRet": false
               }
           ]
       }
    

    Also there is no need for "explicit" $eq operators, since "equals" is actually the default meaning of a value assignment in a query property anyway.