Reputation: 3
I have a customers
collection such as;
{
"_id" : ObjectId("5de8c07dc035532b489b2e23"),
"name" : "sam",
"orders" : [{"ordername" : "cola"},{"ordername" : "cheesecake"}]
}
And waiters
collection such as;
{
"_id" : ObjectId("5de8bc24c035532b489b2e20"),
"waiter" : "jack",
"products" : [{"name" : "cola", "price" : "4"},
{"name" : "water", "price" : "2"},
{"name" : "coffee", "price" : "8" }]
}
{
"_id" : ObjectId("5de8bdc7c035532b489b2e21"),
"waiter" : "susan",
"products" : [{"name" : "cheesecake", "price" : "12" },
{"name" : "apple pie", "price" : "14" }]
}
I want to join the objects from waiters
collection into the customers
collection by matching "products.name" and "orders.ordername". But, the result includes the whole document from the waiters
collection, however, I want only the matched objects inside the document. Here is what I want;
ordered:[
{"name" : "cola", "price" : "4"},
{"name" : "cheesecake", "price" : "12" },
]
I tried $lookup
with and without pipeline, and filter but could not get this result. Thanks in advance.
Upvotes: 0
Views: 440
Reputation: 22276
You had the right idea, we just have to "massage" the data a bit due to its structure like so:
db.collection.aggregate([
{
$addFields: {
"orderNames":
{
$reduce: {
input: "$orders",
initialValue: [],
in: {$concatArrays: [["$$this.ordername"], "$$value"]}
}
}
}
},
{
$lookup:
{
from: "waiters",
let: {orders: "$orderNames"},
pipeline: [
{
$unwind: "$products"
},
{
$match:
{
$expr:{$in: ["$products.name", "$$orders"]},
}
},
{
$group: {
_id: "$products.name",
price: {$first: "$products.price"}
}
},
{
$project: {
_id: 0,
price: 1,
name: "$_id"
}
}
],
as: "ordered"
}
}
])
Upvotes: 1