Replies: 2 comments 1 reply
-
i assume you want to get all Reservations where the listing matches the owner's ( you have 2 options:
the double-query method is to basically search // first query "Listing" collection for the user
const doubleListings = await ListingModel.find({ owner: owner1 }).orFail();
// then query "Reservation" based on the results from "Listing"
const doubleReservations = await ReservationModel.find({ listing: doubleListings.map((v) => v._id) })
.populate('listing')
.orFail(); the other method is to use aggregation via a // the same as the double-query version (actually 3 thanks to populate), just with one aggregate query
const aggregateResult = await ReservationModel.aggregate([
// perform a search on the Listing collection
{
$lookup: {
from: ListingModel.collection.name,
// store the current documents "listing" property for use inside pipeline
let: { listingid: '$listing' },
pipeline: [
{
$match: {
$expr: {
$and: [
// find Listing's where the owner is of the wanted owner
{ $eq: ['$owner', owner1._id] },
// also limit found Listing's to the one from the current Reservation
{ $eq: ['$_id', '$$listingid'] },
],
},
},
},
],
// store result as the "listing" property (overwrite original from Reservation)
// change this value if you dont want the "listing" to be populated along with the "unwind"
as: 'listing',
},
},
{
// create a new document for each element in the array "listing"
// this is safe because the expected result from "$lookup" is only 1 document
$unwind: '$listing',
},
]).exec(); though note that the result from aggregation is never a instance of a mongoose document and always a POJO (Plain old Javascript object) examples of both with datafrom https://github.com/typegoose/typegoose-testing/blob/verify853/src/test.ts output: found double-query data: [
{
_id: new ObjectId("6494a7e4e726c390285cc3c9"),
reservee: new ObjectId("6494a7e4e726c390285cc3c1"),
listing: {
_id: new ObjectId("6494a7e4e726c390285cc3c3"),
name: 'wantedListing',
owner: new ObjectId("6494a7e4e726c390285cc3bd"),
__v: 0
},
name: 'wantedReservation',
__v: 0
}
]
found aggregate data: [
{
_id: new ObjectId("6494a7e4e726c390285cc3c9"),
reservee: new ObjectId("6494a7e4e726c390285cc3c1"),
listing: {
_id: new ObjectId("6494a7e4e726c390285cc3c3"),
name: 'wantedListing',
owner: new ObjectId("6494a7e4e726c390285cc3bd"),
__v: 0
},
name: 'wantedReservation',
__v: 0
}
]
matches? true (Full Reproduction Repository & Branch: https://github.com/typegoose/typegoose-testing/tree/verify853) Disclaimer: i am not experienced in writing aggregation queries, so i dont know if my version is 100% correct or performant |
Beta Was this translation helpful? Give feedback.
-
Thanks very much for this, the aggregation does look complex and I'll need to break it down, right now it isn't working. I get all the Reservation document until I add |
Beta Was this translation helpful? Give feedback.
-
I've trawled through these discussions and googled for hours and not really been able to find a good answer on this. Sorry if I'm just being dense, but any help would be appreciated.
I have a run of the mill booking system with
User
,Listing
andReservation
collections. EachListing
references it's ownerUser
and eachReservation
references the propertyListing
and a reference to theUser
reserving theListing
. I'm sure you can see where I'm going here. I want to be able to run a query/find/where whatever gets me the right answer really so that I can do something along the lines ofReservationModel.find({ "listing.user": userId }).populate(["Listing", "User"])
.Now, from what I've read, it isn't possible for find to work this way, since
populate
is a lazy-load helper utility really. I've read that I should probably denormalize the data, so by that I take it that theReservation
model, should actually contain copies of theUser
andListing
model instances. I suppose that is okay as a last resort, it would mean removing a bunch of existing data, refactoring models and code, but if it truely is the only way then fine. I first of all wanted to ask the community, if there was a better way? So thanks in advance.I've come across this kind of functionality in
prisma
but it could easily be that they are doing multiple requests instead of one, I honestly don't know how it works.Beta Was this translation helpful? Give feedback.
All reactions