在单个集合上使用mongodb$查找

在单个集合上使用mongodb$查找,mongodb,lookup,Mongodb,Lookup,我收集了这样的文件 { "_id" : ObjectId("5773ac6a486f811694711875"), "bsk" : { "bskItems" : [ { "id" : 4, "bskItemLineType" : "SaleItem", "product" : { "description

我收集了这样的文件

{
    "_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
基于
\u id
bsk.bskItems.promotionapplicated.bskIds
\u id
bsk.bskItems.id
加入这两个,但我不知道如何加入。使用文档类型数据库-最好存储促销metadtaa,而不是只存储id。 请参阅附件中的示例

"promotionApplied" : [{
        bskId : 4,
        name : "name",
        otherData : "otherData"
    }, {
        bskId : 5,
        name : "name5",
        otherData : "otherData5"
    }
]

我不知道你是否解决了你的问题,或者这是否与问题有关,但我发现了你的问题:

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"
}
但我的建议是下次在数据库结构中考虑一下。你有苹果和梨,所以我们必须做一个亚洲梨才能得到这个结果。从聚合级别上看,这也不是一件容易的工作。如果您将包含
产品
字段的数组与包含
促销应用
字段的数组分开,那么这可能会容易得多


要将其分解并逐步解释发生的情况:

{
  $unwind: "$bsk.bskItems"
}
通过展开,我们将阵列展平。为了访问数组中的字段并对其执行操作,我们需要使用它。更多关于

在这一行中,我们只是确保每个文档都有一个篮子项目id。在您的情况下,他们都有,我只是添加了它来确保。如果某个文档没有该字段的值,我们将其设置为0(您可以将其设置为-1或任何您想要的值)

这里我们正在为字段
“$bsk.bskItems.promotionapplicated.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"   } }
在最终项目中,我们只是按照我们希望的样子构建最终文档


希望您现在理解思考的原因,以及我们如何保存东西,这很重要。

我建议您调整文档结构,而不是尝试自我引用。MongoDB不是一个传统的数据库。你可能是对的,只是觉得复制描述是不对的,但我看不到其他方法。
{
  $group: {
    _id: { proAppliedId: "$proAppliedId", docId: "$_id"},
    product: { $push:  { "p": "$product" } },
    groupCount: { $sum: 1 }
  }
}
{   $project: {
    _id: "$_id.docId",
    "promotionAppliedto": "$product.p"   } }