Here’s an example through JS code of what I’m trying to achieve:
let waiting = findSessions() // regular query for status "WAITING"
let results = [];
for (let w of waiting) {
// Only push it to results if the w.members[0] and TARGET_USER_ID have never matched before.
// Meaning, in the "session" collection, there are no documents that have these 2 IDs in the members field
if (!hasMatchedBefore(w.members[0], "TARGET_USER_ID")) {
results.push(w);
}
}
IGNORE MOST OF WHAT’S ABOVE
Just realized how poorly written the old question was. Let’s start from the beginning.
Consider the collection "sessions":
[
{
status: "WAITING",
type: "TEXT",
members: [
"adam"
]
},
{
status: "WAITING",
type: "TEXT",
members: [
"john"
]
},
{
status: "WAITING",
type: "VOICE",
members: [
"alex"
]
},
{
status: "ENDED",
type: "VOICE",
members: [
"adam",
"alex"
]
},
{
status: "TIMEOUT",
type: "TEXT",
members: [
"adam",
"TARGET"
]
}
]
I’m making a match-matching system. Let’s say "TARGET" wants to match. I’m trying to write a MongoDB aggregation that does the following.
- Find all documents with query { type: "TEXT", status: "WAITING" }
- Iterate through each document: check if
members[0]
andTARGET
have ever matched before - If
members[0]
andTARGET
have matched before (check entire collection, any type/status), then it will not be included in the final array
It should return the following:
[
{
status: "WAITING",
type: "TEXT",
members: [
"john"
]
},
]
Notice how there were 3 "WAITING" rooms in the collection. But TARGET
had already matched with adam
. And TARGET
cannot match with alex
, because alex
is in a "VOICE" session. So in this case, john
would be the only appropriate match.
2
Answers
I think, I have a solution for you.
Data
Query
Output
Note: Please check mongoplayground link.
Main Solution: https://mongoplayground.net/p/xkyyW8gsWV6
Other Solution: https://mongoplayground.net/p/1ndltdDU38-
One option is to use
$lookup
on the same collection:See how it works on the playground example