2

I have a use case where my query need to find based on 3 optional fields and one of them is pass in as a collection.

The "3 optional fields" part is already solved by this post Spring Data MongoDB AND/OR query with multiple optional parameters

However, I am runnig into the issue with the $in for the collection filed.

For example, in the following query

{ $and : 
    [{
       $and: 
        [
         {$or : [ { $where: '?0 == null' } , { a : ?0 }]}, 
         {$or : [ { $where: '?1 == null' } , { b : ?1 }]},
         {$or : [ { $where: '?2 == null' } , { c : ?2 }]}
        ]
    }]
}

In my case, the field a is actually pass in as a collection, I need to find those object in MongoDB with filed a is $in the collection I passed in.

I have tried with something like this

 { $and : 
        [{
           $and: 
            [
             {$or : [ { $where: '?0 == null' } , { a : { $in : ?0 }}]}, 
             {$or : [ { $where: '?1 == null' } , { b : ?1 }]},
             {$or : [ { $where: '?2 == null' } , { c : ?2 }]}
            ]
        }]
    }

However, I got NPE for this when I pass in a null collection.

Community
  • 1
  • 1
jasonfungsing
  • 1,625
  • 8
  • 22
  • 34

2 Answers2

0

You need to test the collection length, as shown here spring-data-mongo - optional query parameters? You can also get rid of the top-level $and.

{ $and : 
       [
        {$or : [ { $where: '?0.length == 0' } , { a : { $in : ?0 }}]}, 
        {$or : [ { $where: '?1 == null' } , { b : ?1 }]},
        {$or : [ { $where: '?2 == null' } , { c : ?2 }]}
       ]
}
Community
  • 1
  • 1
Marc Tarin
  • 3,109
  • 17
  • 49
0

You actually can't use $in for optional list parameter because when not specified it will be null and $in accept only list. To do that You will have add [] around optional list parameter and then flatten this list like that:

{ $and : 
   [
    {$or : [ { $where: '?0 == null;' },
             { $where: '[].concat.apply([],[?0]).indexOf(this.a) !== -1;'}]}, 
    {$or : [ { $where: '?1 == null' } , { b : ?1 }]},
    {$or : [ { $where: '?2 == null' } , { c : ?2 }]}
   ]
}

use that for mongo version < 3.4 and since 3.4 You can use includes function instead of indexOf

spawlak
  • 1
  • 1