0

I have a given array A = [5, 15, 25, 35].

I have a collection C. All its documents have the field 'numbers', which is an array of numbers, with variable lengths.

I want to match all documents which have, as elements of 'numbers', at least 2 of the 4 elements of A. How should I efficiently proceed?

It would be nice to use find and not need aggregate.

Thank you.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
sheriff
  • 111
  • 5

1 Answers1

0

With aggregation it's easy. You need to use $size with $setIntersection and then match all the documents with element at least 2 numbers in the intersected array:

db.C.aggregate([
    {
        $project: {
            numbers: 1,
            intersectedNumbers: {
                $size: {
                    $setIntersection: ['$numbers', [5,15,25,35]]
                }
            }
        }
    },
    {
        $match: {
            'intersectedNumbers': {
                $gte: 2
            }
        }
    }
])

With find it's more problematic since you need two stages as in the aggregation above, and it's not possible with find. But what you can do, if the A array is dynamic, is to create a function that will return all possibiltes of "at least 2" elements, and then use $or and $all to use find:

db.C.find({
    $or: [
        {numbers: {$all: [5,15]}},
        {numbers: {$all: [5,25]}},
        {numbers: {$all: [5,35]}},
        {numbers: {$all: [15,25]}},
        {numbers: {$all: [15,35]}},
        {numbers: {$all: [25,35]}}
    ]
})
TomG
  • 2,409
  • 4
  • 23
  • 40