可能通过aggregate()
函数在聚合框架中。您需要运行下面的管道,以获得期望的结果:
db.trades.aggregate([
{
"$lookup": {
"from": "subscriptions",
"localField": "clubCode",
"foreignField": "clubCode",
"as": "subs"
}
},
{ "$unwind": "$subs" },
{
"$group": {
"_id": "$clubCode",
"trades": {
"$push": {
"date": "$date",
"wording": { "$concat": ["Achat ", "$name"] },
"amount": "$total"
}
},
"subs": {
"$push": {
"date": "$subs.period",
"wording": { "$concat": ["Subscription ", "$subs.email"] },
"amount": "$subs.amount"
}
}
}
},
{
"$project": {
"clubCode": "$_id",
"_id": 0,
"treasury_moves": { "$setUnion": ["$subs", "$trades"] }
}
}
])
样本输出
/* 1 */
{
"clubCode" : "43W0K",
"treasury_moves" : [
{
"date" : ISODate("2017-01-13T15:03:52.410Z"),
"wording" : "Achat ENGIE SA",
"amount" : 144.87
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2017-01-14T10:52:56.208Z"),
"wording" : "Achat BigBen Interactive",
"amount" : 499.82
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2017-01-13T15:56:32.088Z"),
"wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR",
"amount" : 500.51
},
{
"date" : ISODate("2017-01-13T16:05:35.849Z"),
"wording" : "Achat Visiativ SA",
"amount" : 182.49
}
]
}
在上面的管道,第一阶段包括$lookup
运营商。这允许您对同一数据库中的其他集合执行“左外部联接”,以便从“已加入”集合中对文档进行筛选以进行处理。当您运行对trades
收集管道与 只是这一步:
db.trades.aggregate([
{
"$lookup": {
"from": "subscriptions",
"localField": "clubCode",
"foreignField": "clubCode",
"as": "subs"
}
}
])
,你会得到以下结果:
/* 1 */
{
"_id" : ObjectId("5878ec66ad251f4fb4d2aacc"),
"clubCode" : "43W0K",
"date" : ISODate("2017-01-13T15:03:52.410Z"),
"symbol" : "ENGI.PA",
"name" : "ENGIE SA",
"buyOrSell" : "buy",
"orderDone" : true,
"quantity" : 12,
"price" : 11.99,
"fees" : 0.99,
"total" : 144.87,
"__v" : 0,
"subs" : [
{
"_id" : ObjectId("587c946f3aa3f229a0922761"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922762"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922763"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
}
]
}
/* 2 */
{
"_id" : ObjectId("5878f8c339b47f0ee4a3b80b"),
"clubCode" : "43W0K",
"date" : ISODate("2017-01-13T15:56:32.088Z"),
"symbol" : "PRIO.PA",
"name" : "Lyxor ETF PEA Brazil (Ibovespa) C-EUR",
"buyOrSell" : "buy",
"orderDone" : true,
"quantity" : 56,
"price" : 8.92,
"fees" : 0.99,
"total" : 500.51,
"__v" : 0,
"subs" : [
{
"_id" : ObjectId("587c946f3aa3f229a0922761"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922762"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922763"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
}
]
}
/* 3 */
{
"_id" : ObjectId("5878fadf39b47f0ee4a3b80c"),
"clubCode" : "43W0K",
"date" : ISODate("2017-01-13T16:05:35.849Z"),
"symbol" : "ALVIV.PA",
"name" : "Visiativ SA",
"buyOrSell" : "buy",
"orderDone" : true,
"quantity" : 10,
"price" : 18.15,
"fees" : 0.99,
"total" : 182.49,
"__v" : 0,
"subs" : [
{
"_id" : ObjectId("587c946f3aa3f229a0922761"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922762"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922763"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
}
]
}
/* 4 */
{
"_id" : ObjectId("587a03319e3fe23138119937"),
"clubCode" : "43W0K",
"date" : ISODate("2017-01-14T10:52:56.208Z"),
"symbol" : "BIG.PA",
"name" : "BigBen Interactive",
"buyOrSell" : "buy",
"orderDone" : false,
"orderType" : "ACL",
"quantity" : 83,
"price" : 6.01,
"fees" : 0.99,
"total" : 499.82,
"__v" : 0,
"subs" : [
{
"_id" : ObjectId("587c946f3aa3f229a0922761"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922762"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
},
{
"_id" : ObjectId("587c946f3aa3f229a0922763"),
"email" : "[email protected]",
"clubCode" : "43W0K",
"period" : ISODate("2016-09-01T22:00:00.000Z"),
"amount" : 100,
"type" : "recurrent",
"__v" : 0
}
]
}
在接下来的步骤中,您将需要拼合具有$unwind
的子阵列用于处理作为您的下一个流水线阶段:
db.trades.aggregate([
{
"$lookup": {
"from": "subscriptions",
"localField": "clubCode",
"foreignField": "clubCode",
"as": "subs"
}
},
{ "$unwind": "$subs" }
])
这将产生i x j
文档,其中i
是原始集合(4)中的文档数量,而j
是数组元素数量(3)。
下一步,$group
,然后将组中的12份文件由clubCode
字段,并创建两个阵列与来自字段中指定的子文档:在管道
db.trades.aggregate([
{
"$lookup": {
"from": "subscriptions",
"localField": "clubCode",
"foreignField": "clubCode",
"as": "subs"
}
},
{ "$unwind": "$subs" },
{
"$group": {
"_id": "$clubCode",
"trades": {
"$push": {
"date": "$date",
"wording": { "$concat": ["Achat ", "$name"] },
"amount": "$total"
}
},
"subs": {
"$push": {
"date": "$subs.period",
"wording": { "$concat": ["Subscription ", "$subs.email"] },
"amount": "$subs.amount"
}
}
}
}
])
输出
/* 1 */
{
"_id" : "43W0K",
"trades" : [
{
"date" : ISODate("2017-01-13T15:03:52.410Z"),
"wording" : "Achat ENGIE SA",
"amount" : 144.87
},
{
"date" : ISODate("2017-01-13T15:03:52.410Z"),
"wording" : "Achat ENGIE SA",
"amount" : 144.87
},
{
"date" : ISODate("2017-01-13T15:03:52.410Z"),
"wording" : "Achat ENGIE SA",
"amount" : 144.87
},
{
"date" : ISODate("2017-01-13T15:56:32.088Z"),
"wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR",
"amount" : 500.51
},
{
"date" : ISODate("2017-01-13T15:56:32.088Z"),
"wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR",
"amount" : 500.51
},
{
"date" : ISODate("2017-01-13T15:56:32.088Z"),
"wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR",
"amount" : 500.51
},
{
"date" : ISODate("2017-01-13T16:05:35.849Z"),
"wording" : "Achat Visiativ SA",
"amount" : 182.49
},
{
"date" : ISODate("2017-01-13T16:05:35.849Z"),
"wording" : "Achat Visiativ SA",
"amount" : 182.49
},
{
"date" : ISODate("2017-01-13T16:05:35.849Z"),
"wording" : "Achat Visiativ SA",
"amount" : 182.49
},
{
"date" : ISODate("2017-01-14T10:52:56.208Z"),
"wording" : "Achat BigBen Interactive",
"amount" : 499.82
},
{
"date" : ISODate("2017-01-14T10:52:56.208Z"),
"wording" : "Achat BigBen Interactive",
"amount" : 499.82
},
{
"date" : ISODate("2017-01-14T10:52:56.208Z"),
"wording" : "Achat BigBen Interactive",
"amount" : 499.82
}
],
"subs" : [
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
},
{
"date" : ISODate("2016-09-01T22:00:00.000Z"),
"wording" : "Subscription [email protected]",
"amount" : 100
}
]
}
您需要与$setUnion
运营商加入两个数组,而忽略重复在您的最终聚合管道,$project
。这也将重塑文档,将_id
密钥替换为clubCode
字段。运行这些阶段的最终管道将为您提供理想的结果。
哇,令人印象深刻!非常感谢,它工作得很好,我现在明白了(呃...我相信... :))一切的工作! 再次感谢! – Toma
不用担心,总是乐意帮助:)如果您需要对管道进行进一步的说明,请随时在评论中给我留言。 – chridam
现在,没有关于你给我什么的其他问题。 只是另一件事,我想按日期排序结果。我试图在流水线中添加“排序”,但我没有成功对它们进行排序。 我试图把'{$ sort:{treasury_moves.date:1}}'放在'$ project'之后,但它不起作用。 如果我把它放在$ unwind之后,我可以对每个集合进行排序,但不能放在一起。 你有任何解决方案吗? 谢谢! :) – Toma