Hi suppose I have these two collections
sample1 :
{
"_id" : {
"date" : ISODate("2020-02-11T18:30:00Z"),
"price" : 4,
"offer" : 0,
"itemCode" : "A001"
"customerId" : ObjectId("5e43de778b57693cd46859eb"),
"sellerId" : ObjectId("5e43e5cdc11f750864f46820"),
},
"charges" : 168
}
{
"_id" : {
"date" : ISODate("2020-02-11T18:30:00Z"),
"coverPrice" :5.5 ,
"offer" : 38,
"itemCode" : "B001"
"customerId" : ObjectId("5e43de778b57693cd46859eb"),
"sellerId" : ObjectId("5e43e5cdc11f750864f46820"),
},
"charges" : 209.5
}
NOTE : sample1's _id
doesnot have any ObjectId()
.
sample2 :
{
"paymentReceivedOnDate" : ISODate("2020-02-12T18:30:00Z"),
"customerId" : ObjectId("5e43de778b57693cd46859eb"),
"sellerId" : ObjectId("5e43e5cdc11f750864f46820"),
"amount" : 30,
}
{
"paymentReceivedOnDate" : ISODate("2020-02-12T18:30:00Z"),
"customerId" : ObjectId("5e43de778b57693cd46859eb"),
"sellerId" : ObjectId("5e43e5cdc11f750864f46820"),
"amount" : 160,
}
{
"paymentReceivedOnDate" : ISODate("2020-02-11T18:30:00Z"),
"customerId" : ObjectId("5e43de778b57693cd46859eb"),
"sellerId" : ObjectId("5e43e5cdc11f750864f46820"),
"amount" : 50,
}
My problem statements :
1: Firstly i need to calculate the totalCharges from sample 1 collection. against the [date,customerId,sellerId ]
2: Secondly i need to calculate totalAmount from sample 2 collection.
3: Than i need calculte the outstanding ie [totalCharges - totalAmount].
4: lastly and most importantly i need to save the projected result into a new collection suppose "result" with the following fields-['customerId','sellerId','date','totalCharges','outstanding'(ie: [totalCharges - totalAmount]),'totalAmount'.
You can try below query :
db.sample1.aggregate([
/** groups data & sum up charges */
{ $group: { _id: { date: '$_id.date', customerId: '$_id.customerId', sellerId: '$_id.sellerId' }, totalCharges: { $sum: '$charges' } } },
/** finds matching docs from sample2 */
{
$lookup:
{
from: "sample2",
let: { customerId: '$_id.customerId', sellerId: '$_id.sellerId' },
pipeline: [
{
$match:
{
$expr:
{
$and:
[
{ $eq: ["$customerId", "$$customerId"] },
{ $eq: ["$sellerId", "$$sellerId"] }
]
}
}
},
{ $project: { amount: 1, _id: 0 } }
],
as: "TotalAmount" // TotalAmount is an array of objects, each object will have just amount field in it.
}
},
/** retains only needed fields */
{
$project: {
totalCharges: 1, outstanding: {
$subtract: ['$totalCharges', {
$reduce: {
input: '$TotalAmount',
initialValue: 0,
in: { $add: ["$$value", "$$this.amount"] }
}
}]
}, TotalAmount: {
$reduce: {
input: '$TotalAmount',
initialValue: 0,
in: { $add: ["$$value", "$$this.amount"] }
}
}
}
}
])
Test : MongoDB-Playground
Ref : aggregation-pipeline
Note : At the end of the aggregation you can have either $merge or $out stage to write aggregation results into new collection, If your MongoDB v >= 4.2
then prefer $merge
cause it will merge fields to existing documents/adds new documents to existing collection or if no collection is found with given name it would create new collection, But where as $out
will completely replaces existing collection if provided collection name already exists or creates new collection with provided name.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.