Given multiples documents containing a key named userId, where this key is always an object:
{
"_id": {
"$oid": "22fc6b11a0ff111d598b114f"
},
"userId": {
"KEY1" : ["..."],
"KEY2" : ["..."],
"KEY3" : ["..."],
"KEY4" : ["..."]
},
}
It will always contain 4 sub-keys, where each of these is always a non-empty array of strings
How I can search over all documents looking inside each of these KEY's?
For example:
/* MONGO document
{
"_id": {
"$oid": "65fc6b08a0ffe6dd598b114f"
},
"userId": {
"KEY1" : ["1", "2", "3"],
"KEY2" : ["A", "Z"]
...
}
},
{
"_id": {
"$oid": "22fc6b11a0ff111d598b114f"
},
"userId": {
"KEY1" : ["4", "5", "6"],
"KEY2" : ["Z", "X"]
...
},
}
*/
const array = ["2", "X"];
const users = await db.collection("users").find({ "userId": { "$in": array } }).toArray();
console.log(users)
const array = ["2", "X"]; <- I'm trying to specify an array of strings and find all documents
that contains any of these strings in any of the sub-keys arrays of the userId object
In this case, it would match both documents, because 2 exists on the first document userId.KEY1
and X exists on the second document userId.KEY2
const array = ["X"]; This would match just the second document
My attempt is not finding any match, how i could achieve this?
You can use
$setIntersectionof the inputarraywith the$setUnionof the values of KEY's. Note however that this requires mongo to construct the Union before doing the intersection check which may not be very optimal and won't use any indexes.Mongo Plaground
And if you have many KEY's, it fits well with jQueeny's answer of constructing a string of $KEY's to use in the
setUnionpart.If you did have an arbitrary number of KEYs - and not always the exact same 4 - you can also use
$objectToArrayas suggested in the comments:Mongo Playground
Also won't use any index so I'd recommend jQueeny's answer over this for your scenario.