在MongoDB中从另一个集合中执行数组查找。

huangapple go评论122阅读模式
英文:

perform lookup on array from another collection in MongoDB

问题

我有一组订单。每个订单都有一系列商品,每个商品都有catalog_id,它是指向目录集合的ObjectId

我需要一个聚合查询,以扩展方式检索特定的订单 - 每个订单及其商品,包括目录的名称SKU

原始数据结构:

Orders: [{
 _id : ObjectId('ord1'),
items : [{
   catalog_id: ObjectId('xyz1'),
   qty: 5
},
{
   catalog_id: ObjectId('xyz2'),
   qty: 3
}]
Catalogs: [{
 _id : ObjectId('xyz1') 
name: 'my catalog name',
SKU: 'XxYxZx1'
},{
 _id : ObjectId('xyz2') 
name: 'my other catalog name',
SKU: 'XxYxZx2'
}]

理想的结果应该是:

Orders: [{
 _id : ObjectId('ord1'),
items : [{
   catalog_id: ObjectId('xyz1'),
   catalog_name: 'my catalog name',
   catalog_SKU: 'XxYxZx1' , 
   qty: 5
},
{
   catalog_id: ObjectId('xyz2'),
   catalog_name: 'my other catalog name',
   catalog_SKU: 'XxYxZx2' , 
   qty: 3
}]

到目前为止,我所做的是:

db.orders.aggregate([
    {
        $match: {merchant_order_id: 'NIM333'}
    },
    {
        $lookup: {
          from: "catalogs",
          //localField: 'items.catalog_id',
          //foreignField: '_id',
          let: { 'catalogId' : 'items.catalog_id' },
          pipeline: [
              {
                $match : {$expr:{$eq:["$catalogs._id", "$$catalogId"]}}
              },
              {
                  $project: {"name": 1, "merchant_SKU": 1 }
              }
          ],
          as: "items_ex"
        },
    },
])

但是items_ex 为空,原因我无法理解。

英文:

I have a collection of Orders. each order has a list of Items, and each Item has catalog_id, which is an ObjectId pointing to the Catalogs collection.
I need an aggregate query that will retrieve certain orders - each order with its Items in extended fashion including the Catalog name and SKU. i.e:

Original data structure:

Orders: [{
 _id : ObjectId('ord1'),
items : [{
   catalog_id: ObjectId('xyz1'),
   qty: 5
},
{
   catalog_id: ObjectId('xyz2'),
   qty: 3
}]
Catalogs: [{
 _id : ObjectId('xyz1') 
name: 'my catalog name',
SKU: 'XxYxZx1'
},{
 _id : ObjectId('xyz2') 
name: 'my other catalog name',
SKU: 'XxYxZx2'
}
]

ideal outcome would be:

Orders: [{
 _id : ObjectId('ord1'),
items : [{
   catalog_id: ObjectId('xyz1'),
   catalog_name: 'my catalog name',
   catalog_SKU: 'XxYxZx1' , 
   qty: 5
},
{
   catalog_id: ObjectId('xyz2'),
   catalog_name: 'my other catalog name',
   catalog_SKU: 'XxYxZx2' , 
   qty: 3
}
]

What I did so far was:

db.orders.aggregate(
    [
    {
        $match: {merchant_order_id: 'NIM333'}
    },
    {
        $lookup: {
          from: "catalogs",
          //localField: 'items.catalog_id',
          //foreignField: '_id',
          let: { 'catalogId' : 'items.catalog_id' },
          pipeline: [
              {
                $match : {$expr:{$eq:["$catalogs._id", "$$catalogId"]}}
              },
              {
                  $project: {"name": 1, "merchant_SKU": 1 }
              }
          ],
          as: "items_ex"
        },
    },
])

but items_ex comes out empty for some reason i cannot understand.

答案1

得分: 1

你在定义管道变量时缺少了美元符号。应该是:

let: { 'catalogId' : '$items.catalog_id' },

而且这个表达式返回一个数组,所以你需要使用 $in 而不是 $eq

{
    $lookup: {
        from: "catalogs",
        let: { 'catalogId' : 'items.catalog_id' },
        pipeline: [
            {
                $match : {$expr:{$in:["$_id", "$$catalogId"]}}
            },
            {
                $project: {"name": 1, "merchant_SKU": 1 }
            }
        ],
        as: "items_ex"
    }
}

Mongo Playground

英文:

You're missing a dollar sign when you define your pipeline variable. There should be:

let: { 'catalogId' : '$items.catalog_id' },

and also this expression returns an array to you need $in instead of $eq:

{
    $lookup: {
    from: "catalogs",
    let: { 'catalogId' : 'items.catalog_id' },
    pipeline: [
        {
            $match : {$expr:{$in:["$_id", "$$catalogId"]}}
        },
        {
            $project: {"name": 1, "merchant_SKU": 1 }
        }
    ],
    as: "items_ex"
    }
}

Mongo Playground

答案2

得分: 1

你需要首先使用 $unwind 解开 items 数组,然后使用 $group 重新构建数组,以匹配 items 数组中 qtycatalogs_id 的精确位置。

db.orders.aggregate([
  { "$match": { "merchant_order_id": "NIM333" }},
  { "$unwind": "$items" },
  { "$lookup": {
    "from": "catalogs",
    "let": { "catalogId": "$items.catalog_id", "qty": "$items.qty" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": ["$_id", "$$catalogId"] } }},
      { "$project": { "name": 1, "merchant_SKU": 1, "qty": "$$qty" }}
    ],
    "as": "items"
  }},
  { "$unwind": "$items" },
  { "$group": {
    "_id": "$_id",
    "items": { "$push": "$items" },
    "data": { "$first": "$$ROOT" }
  }},
  { "$replaceRoot": {
    "newRoot": {
      "$mergeObjects": ["$data", { "items": "$items" }]
    }
  }}
])

MongoPlayground

英文:

You need to first $unwind the items and reconstruct the array back using $group to match the exact position of qty with the catalogs_id inside the items array

db.orders.aggregate([
  { "$match": { "merchant_order_id": "NIM333" }},
  { "$unwind": "$items" },
  { "$lookup": {
    "from": "catalogs",
    "let": { "catalogId": "$items.catalog_id", "qty": "$items.qty" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": ["$_id", "$$catalogId"] } }},
      { "$project": { "name": 1, "merchant_SKU": 1, "qty": "$$qty" }}
    ],
    "as": "items"
  }},
  { "$unwind": "$items" },
  { "$group": {
    "_id": "$_id",
    "items": { "$push": "$items" },
    "data": { "$first": "$$ROOT" }
  }},
  { "$replaceRoot": {
    "newRoot": {
      "$mergeObjects": ["$data", { "items": "$items" }]
    }
  }}
])

MongoPlayground

huangapple
  • 本文由 发表于 2020年1月6日 20:45:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/59612375.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定