michael michael - 1 year ago 48
Node.js Question

Select documents where all values in an array field exist in another array

I wasn't quite sure how to title this!

So I have an array of product IDs

var productIds = [139,72,73,1,6]

And a bunch of customer documents in MongoDB

name: 'James',
products: [ 73, 139 ],
_id: 5741cff3f08e992598d0a39b

name: 'John',
products: [ 72, 99 ],
_id: 5741d047f08e992598d0a39e

I would like to find customers when all of their products appear in the array of product IDs (productIds)

I tried:

'products' : {
'$in': productIds

But that returns John, even though 99 doesn't exist in the list of product IDs

I also tried:

'products' : {
'$all': productIds

Which returns nothing because none of the customer have ALL the products

Is there a way to achieve what I need in a single query or am I going to have to do some post query processing?

I also tried

'products': {
'$in': productIds,
'$not': {
'$nin': productIds

but this also seems to return customers when not all product IDs match

Answer Source

You can do this using the .aggregate() method and the $redact operator. In your $cond expressions you need to use the $setIsSubset in order to check if all the elements in the "products" array are in "productIds". This is because you cannot use $in in the conditional expression

var productIds = [139,72,73,1,6];
    { "$redact": { 
        "$cond": [ 
            { "$setIsSubset": [ "$products", productIds ] },