我有一个包含这样的文档的集合
{
"_id" : ObjectId("5773ac6a486f811694711875"),
"bsk" : {
"bskItems" : [
{
"id" : 4,
"bskItemLineType" : "SaleItem",
"product" : {
"description" : "reblochon"
}
},
{
"id" : 5,
"bskItemLineType" : "SaleItem",
"product" : {
"description" : "Pinot Noir"
}
},
{
"id" : 13,
"bskItemLineType" : "PromotionItem",
"promotionApplied" : {
"bskIds" : [
4,
5
]
}
},
{
"id" : 8,
"bskItemLineType" : "SaleItem",
"product" : {
"description" : "Food"
}
},
{
"id" : 10,
"bskItemLineType" : "SubTotalItem"
},
{
"id" : 12,
"bskItemLineType" : "TenderItem"
},
{
"id" : 14,
"bskItemLineType" : "ChangeDue"
}
]
}
}
我想要一个输出,我可以看到“promotionsApplied”以及它们应用的项目的描述。对于上面的文档,“promotionsApplied”是“bsk.BskItems.id”4和5所以我希望输出为:
{
"_id": xxxxx,
"promotionAppliedto : "reblochon"
},
{
"_id": xxxxx,
"promotionAppliedto : "Pinot Noir"
}
以下查询:
db.getCollection('DSTest').aggregate([
{$project:{"bsk.bskItems.product.description":1,"bsk.bskItems.id":1}},
{$unwind: "$bsk.bskItems"},
])
给我说明
db.getCollection('DSTest').aggregate([
{$project:{"bsk.bskItems.promotionApplied.bskIds":1}},
{$unwind: "$bsk.bskItems"},
{$unwind:"$bsk.bskItems.promotionApplied.bskIds"},
])
让我获得促销活动。我希望能够使用$lookup
根据_id
和bsk.bskItems.promotionApplied.bskIds
以及_id
和bsk.bskItems.id
加入这两者,但我无法弄清楚如何。
答案 0 :(得分:1)
我不知道你是否解决了问题,或者这是否相关,但我想出了你的问题:
db.DSTest.aggregate([
{
$unwind: "$bsk.bskItems"
},
{
$project: {
baItId: { $ifNull: [ "$bsk.bskItems.id", 0 ] },
"bsk": {
"bskItems": {
"promotionApplied": {
"bskIds": { $ifNull: [ "$bsk.bskItems.promotionApplied.bskIds", [0] ] }
}
}
},
"product": { $ifNull: [ "$bsk.bskItems.product.description", "" ] },
}
},
{
$unwind: "$bsk.bskItems.promotionApplied.bskIds"
},
{
$project: {
baItId: 1,
proAppliedId:
{
$cond: { if: { $eq: [ "$bsk.bskItems.promotionApplied.bskIds", 0 ] }, then: "$baItId", else: "$bsk.bskItems.promotionApplied.bskIds" }
},
product: 1
}
},
{
$group: {
_id: { proAppliedId: "$proAppliedId", docId: "$_id"},
product: { $push: { "p": "$product" } },
groupCount: { $sum: 1 }
}
},
{
$unwind: "$product"
},
{
$match: {
"product.p": {$ne: ""}, "groupCount": { $gt: 1}
}
},
{
$project: {
_id: "$_id.docId",
"promotionAppliedto": "$product.p"
}
}
])
使用虚拟文档,这是我得到的结果:
{
"_id" : ObjectId("5773ac6a486f811694711875"),
"promotionAppliedto" : "reblochon"
}
{
"_id" : ObjectId("5773ac6a486f811694711875"),
"promotionAppliedto" : "Pinot Noir"
}
但我的建议是下次在你的数据库结构中加入一些思考。你有苹果和梨,所以我们必须做一个亚洲梨才能得到这个结果。同样从聚合级别看,这不是一件容易的事。如果您将包含字段product
的数组与包含字段promotionApplied
的数组分开,那可能会容易得多。
要分解并逐步解释发生的事情:
{
$unwind: "$bsk.bskItems"
}
通过展开,我们正在展平我们的阵列。我们需要这个来访问数组中的字段并对它们进行操作。有关$unwind
的更多信息{
$project: {
baItId: { $ifNull: [ "$bsk.bskItems.id", 0 ] },
"bsk": {
"bskItems": {
"promotionApplied": {
"bskIds": { $ifNull: [ "$bsk.bskItems.promotionApplied.bskIds", [0] ] }
}
}
},
"product": { $ifNull: [ "$bsk.bskItems.product.description", "" ] },
}
}
baItId: { $ifNull: [ "$bsk.bskItems.id", 0 ] }
通过这一行,我们只需确保每个文档都获得一个篮子项ID。在你的情况下他们都这样做,我只是添加它以确保。如果某个文档没有该字段的值,我们将其设置为0(您可以将其设置为-1或任何您想要的值)
"bsk": {
"bskItems": {
"promotionApplied": {
"bskIds": { $ifNull: [ "$bsk.bskItems.promotionApplied.bskIds", [0] ] }
}
}
}
我们在这里为字段"$bsk.bskItems.promotionApplied.bskIds"
创建一个数组。由于并非所有文档都有此字段,我们必须将它们全部添加到其中,否则我们会将橙子与苹果进行比较。
"product": { $ifNull: [ "$bsk.bskItems.product.description", "" ] }
如前所述,我们必须使我们的文档看起来完全相同,因此我们还将$bsk.bskItems.product.description
添加到没有此字段的文档中。那些没有字段的人我们将其设置为空字符串
现在我们所有的文档都具有相同的结构,我们可以从实际的整理开始。
{
$unwind: "$bsk.bskItems.promotionApplied.bskIds"
}
由于我们想要访问$bsk.bskItems.promotionApplied.bskIds
内的ID,我们也必须解开这个数组。
{
$project: {
baItId: 1,
proAppliedId:
{
$cond: { if: { $eq: [ "$bsk.bskItems.promotionApplied.bskIds", 0 ] }, then: "$baItId", else: "$bsk.bskItems.promotionApplied.bskIds" }
},
product: 1
}
}
baItId: 1
和product: 1
正在传递中。 proAppliedId
将包含我们的bsk.bskItems.promotionApplied.bskIds
。如果它们为0,则获得与字段$baItId
相同的ID,否则它们会保留其ID。
{
$group: {
_id: { proAppliedId: "$proAppliedId", docId: "$_id"},
product: { $push: { "p": "$product" } },
groupCount: { $sum: 1 }
}
}
现在我们终于可以按照我们在前一个聚合管道中创建的$proAppliedId
对文档进行分组。
我们还将产品值推送到数组中。所以现在将有包含两个条目的数组。
一个具有我们查找的值,另一个具有空字符串,因为我们在之前的聚合管道"product": { $ifNull: [ "$bsk.bskItems.product.description", "" ] }
中执行了该操作
我们还创建了一个名为groupCount
的新字段来计算组合在一起的文档。
{ $project: {
_id: "$_id.docId",
"promotionAppliedto": "$product.p" } }
在最终项目中,我们只是按照我们希望的样子来构建最终文档。
希望你现在明白为什么思考,是和我们如何拯救事物,重要。
答案 1 :(得分:0)
使用文档类型数据库 - 最好存储促销metadtaa而不是id。 请参阅附件中的例子
"promotionApplied" : [{
bskId : 4,
name : "name",
otherData : "otherData"
}, {
bskId : 5,
name : "name5",
otherData : "otherData5"
}
]