0

I have such documents in Mongo:

{
  _id: 1,
  cat: ['a', 'b, 'c', 'd', 'e']
},
{
  _id: 2,
  cat: ['f', 'g, 'h', 'i', 'j']
},
{
  _id: 3,
  cat: ['a', 'b, 'f', 'g', 'h']
},
{
  _id: 4,
  cat: ['i', 'j, 'c', 'd', 'e']
}

and I have to filter the documents that have at least n occurrences (let' say 3) of 'cat' in a set I have, i.e.:

['a', 'b', 'c', 'f']

So in this case only the documents with _id equal to 1 and 3 should be returned because both of them have at least 3 occurrences of the categories present in the requested array.

What is the best way to solve this problem? Should I relay on aggregation framework or is there any easy way to do without it?

2 Answers 2

3

you can achive this using $setIntersection operator

db.collection.aggregate(
   [
     {$project: {cat: 1, inter: { $setIntersection: [ "$cat", ['a', 'b', 'c', 'f'] ] } } }, 
     {$project: {cat: 1, size: {$size: "$inter"}}},
     {$match: {size: {$gte: 3}}}
   ]
)

output:

{ "_id" : 1, "cat" : [ "a", "b", "c", "d", "e" ], "size" : 3 }
{ "_id" : 3, "cat" : [ "a", "b", "f", "g", "h" ], "size" : 3 }

try it online: mongoplayground.net/p/Bv-Tdl5ii7l

Sign up to request clarification or add additional context in comments.

1 Comment

Really nice and clean solution!
1

You can try $redact with $setIntersection for your query.

$setIntersection to compare the cat array with input array and return array of common names documents followed by $size and $redact and compare result with 3 to keep and else remove the document.

db.collection.aggregate(
    [{
        $redact: {
            $cond: {
                if: {
                    $gte: [{
                        $size: {
                            $setIntersection: ["$cat", ['a', 'b', 'c', 'f']]
                        }
                    }, 3]
                },
                then: "$$KEEP",
                else: "$$PRUNE"
            }
        }
    }]
)

1 Comment

Really nice and clean solution!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.