I’ve 2 Collection which Address & Users each user Can have multiple address I want to show the name of user & his address in a table… Users collection:
{
_id:
clientName:
}
Address collection:
{
addressId:
addressName:
clientId
}
I don’t use my query in publish, my query is in report generation.
Since your Address collection is referencing the clientId this implies that each address is only for one client, i.e. the same address cannot be shared by multiple clients.
In that case you should get rid of the Address collection and simply embed the addresses within the user document. This is frowned upon in SQL, but is actually the recommended way with mongo: Model One-to-Many Relationships with Embedded Documents.
While the response above is correct (every address is associated directly with a user, so it might as well be in an array of embedded documents), if you don’t want to change your model you could use the $lookup operator with the model you specified.
You might need to use Users.rawCollection() or use the mongodb official driver, in order to utilize Mongo’s aggregation functions. This might look something like:
async function usersWithAddresses() {
const collection = Users.rawCollection()
const result = await collection.aggregate([
{
$lookup: {
from: 'address',
localField: '_id',
foreignField: 'clientId',
// This will output an array of results on the field 'addresses'
as: 'addresses'
}
}
]).toArray()
return result
}
So this query is creating a field addresses in the query results that is an array of embedded documents. The data for this field comes from another collection, so you might say it’s a kind of join…
const result = allTrips.aggregate([
{
$lookup: {
from: 'user_data',
// Per docs, "The pipeline cannot directly access the input document fields.
// Instead, first define the variables for the input document fields,
// and then reference the variables in the stages in the pipeline."
let: { created_by: "$created_by" },
pipeline: [
$match: {
$expr: { $eq: [ "$user_id", "$created_by" ] }
},
$project: {
// Fields you want to include/exclude
emails: 1
}
]
as: 'users_details',
}
},
// ...
}].toArray()
@mixmatric Actually you should be able to specify the field(s) on user_details in your original $project object by simply specifying the field path like 'user_details.emails': 1. That way you can use the simpler join using localField and foreignField.
In one of my queries there are three levels of nesting, so I noticed that loading big dataset can take a while… once it starts really bothering me, I will try to experiment with $lookup, whether that would be faster.
In my other projects, I started off with nesting the documents as arrays and now I am at the stage when I hate it, because querying such dataset for reporting is very slow. I basically have to unwind all the documents beforehand.