In below example, looking for new partner suggestions for user abc. abc
has already sent a request to 123
so that can be ignored. rrr
has sent request to abc
but rrr
is in the fromUser
field so rrr
is still a valid row to be shown as suggestion to abc
I have two collections:
- User collection
[
{
_id: "abc",
name: "abc",
group: 1
},
{
_id: "xyz",
name: "xyyy",
group: 1
},
{
_id: "123",
name: "yyy",
group: 1
},
{
_id: "rrr",
name: "tttt",
group: 1
},
{
_id: "eee",
name: "uuu",
group: 1
}
]
- Partnership collection (if users have already partnered)
[
{
_id: "abc_123",
fromUser: "abc",
toUser: "123"
},
{
_id: "rrr_abc",
fromUser: "rrr",
toUser: "abc"
},
{
_id: "xyz_rrr",
fromUser: "xyz",
toUser: "rrr"
}
]
My query below excludes the user rrr
but it should not because its not listed in toUser
field in the partnership collection corresponding to the user abc
.
How to modify this query to include user rrr
in this case?
db.users.aggregate([
{
$match: {
group: 1,
_id: {
$ne: "abc"
}
}
},
{
$lookup: {
from: "partnership",
let: {
userId: "$_id"
},
as: "prob",
pipeline: [
{
$set: {
users: [
"$fromUser",
"$toUser"
],
u: "$$userId"
}
},
{
$match: {
$expr: {
$and: [
{
$in: [
"$$userId",
"$users"
]
},
{
$in: [
"abc",
"$users"
]
}
]
}
}
}
]
}
},
{
$match: {
"prob.0": {
$exists: false
}
}
},
{
$sample: {
size: 1
}
},
{
$unset: "prob"
}
])
3
Answers
Your current query does not allow creating an existing connection regardless of the connection direction. If the order of the connection is important use:
See how it works on the playground example
For MongoDB 5 and later, I’d propose the following aggregation pipeline:
The following documents are returned (full result without the $sample stage):
The main difference is that the lookup connects the collections by the
toUser
field (seelocalField
,foreignField
) and uses a minimal pipeline to restrict the results further to only retrieve the requests from the current user document to "abc".See this playground to test.
When using MongoDB < 5, you cannot use
localField
andforeignField
to run the pipeline only on a subset of the documents in the * from*collection. To overcome this, you can use this aggregation pipeline:
The results are the same as for the upper pipeline.
See this playground to test.
For another, another way, this query starts from the
partnership
collection, finds which users to exclude, and then does a"$lookup"
for everybody else. The remainder is just output formatting, although it looks like you may want to add a"$sample"
stage at the end.Try it on mongoplayground.net.