Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 这是连接两个集合并合并结果的正确方法吗_Mongodb_Mongodb Query - Fatal编程技术网

Mongodb 这是连接两个集合并合并结果的正确方法吗

Mongodb 这是连接两个集合并合并结果的正确方法吗,mongodb,mongodb-query,Mongodb,Mongodb Query,我正在尝试联接两个集合并从两个集合中获取字段。集合具有非常基本的结构,其外观如下: "products": [ { "_id": 0, "name": "product 0", "desc": "some product", "sales_reps": [ { &qu

我正在尝试联接两个集合并从两个集合中获取字段。集合具有非常基本的结构,其外观如下:

"products": [
    {
      "_id": 0,
      "name": "product 0",
      "desc": "some product",
      "sales_reps": [
        {
          "sales_rep_id": 0,
          "is_doing_good": true
        },
        {
          "sales_rep_id": 1,
          "is_doing_good": true
        }
      ]
    }
  ]

  "sales_rep_master": [
    {
      "_id": 0,
      "name": "sales rep 0"
    },
    {
      "_id": 1,
      "name": "sales rep 1"
    },
    {
      "_id": 2,
      "name": "sales rep 2"
    }
  ]
我正试图在
products.sales\u reps.sales\u rep\u id=sales\u rep\u master.\u id
上加入他们。我的查询是这样的:

[
  {
    "$match": { <--Filter on product._id
      "_id": 0 
    }
  },
  {
    "$unwind": { <-- Expand sales reps array
      "path": "$sales_reps" 
    }
  },
  {
    "$lookup": { <-- join with sales rep master and filter our where is_doing_well is false
      "from": "sales_rep_master",
      "let": {
        "sr_id": "$sales_reps.sales_rep_id",
        "is_doing_well": "$sales_reps.is_doing_good"
      },
      "pipeline": [
        {
          "$match": {
            "$and": [
              {
                "$expr": {
                  "$eq": [
                    "$_id",
                    "$$sr_id"
                  ]
                }
              },
              {
                "$expr": {
                  "$eq": [
                    "$$is_doing_well",
                    true
                  ]
                }
              }
            ]
          }
        },
        {
          "$addFields": {
            "doing_good": "$$is_doing_well"
          }
        }
      ],
      "as": "sales_reps"
    }
  },
  {
    "$unwind": { <<- expand newly created sales reps array
      "path": "$sales_reps"
    }
  },
  {
    "$group": { <-- Group product and sales reps
      "_id": "$_id",
      "product": {
        "$first": "$$ROOT"
      },
      "sales_reps": {
        "$push": "$sales_reps"
      }
    },
    
  },
  {
    "$set": { <-- add sales_reps inside product
      "product.sales_reps": "$sales_reps"
    }
  },
  {
    "$replaceRoot": { <-- replace root
      "newRoot": "$product"
    }
  }
]
[
{

“$match”:{可以简化的部分是使用
localField
foreignField

然后,我将另一种方法与
$project
绑定,而不是
$set
$replaceRoot



您可以优化查询

  • $match
    您可以同时满足这两个条件,以减少不匹配的文档
  • $unwind
    解构
    销售代表
    数组
  • $match
    销售代表在减少不匹配文档方面做得好吗
  • $lookup
    加入集合
  • $unwind
    解构
    销售代表
  • $addFields
    添加字段
    做得好
  • $group
    按id并重建
    销售代表
    阵列


另一种可能的方法是,从上述示例中减少
$addFields
管道

  • $mergeObjects
    合并侧面的字段
    $push


对于下面的参考,使用


<> P>我很少考虑。对于每个条件,你不需要使用<代码> $Exp>/Cudio。如果你要使用<代码> $ < /COD>比较,那么你不需要<代码> $un/<代码>。<代码> $ un/<代码> >总是在我们增加数据时。Ref。但是考虑数据大小,你可以使用<代码> $< /Calp>或<代码> $ un/<代码> < < /P>
db.products.aggregate([
  {
    "$match": {
      "_id": 0
    }
  },
  {
    $addFields: {
      sales_reps: {
        $filter: {
          input: "$sales_reps",
          cond: {
            $eq: [ "$$this.is_doing_good", true]
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "sales_rep_master",
      "let": { "sr_id": "$sales_reps.sales_rep_id" },
      "pipeline": [
        {
          "$match": {
            "$expr": {
              "$and": [
                { "$in": [ "$_id","$$sr_id"] },
                // { other condition }
              ]
            }
          }
        },
        {
          "$addFields": {
            "doing_good": true
          }
        }
      ],
      "as": "sales_reps"
    }
  }
])

工作

我只需要知道,
{“$expr”:{“$eq”:[“$$is_做得很好”,true]}
为什么要在管道内检查此项?管道是使用联接表阶段。
做得好吗
在您的
产品中。因此,如果您需要检查
做得好吗:真的
,您可以在查找之前进行检查。这对您有帮助,如果有,我可以简要回答我的问题,
$in
如果提供索引,ookup管道将不使用索引,请查看此链接并遵循链接和票证。@Turivshal我刚刚查看了票证。
$unwind
当我们知道有数千条记录时,性能会更差。@Turivshal和他表示需要匹配两个变量。(可能他的设想是错误的,我对此表示怀疑).我可以进行常规查找,需要更多stages@varman是的,你的$unwind是对的,看看这个问题,在第一个管道中,他正在使用
\u id
搜索,它将只返回一个文档,第二个我认为存储数千个数组元素不是一个好方法,如果数组字段包含有限的数据,那么这对你来说是一个好办法nwind仅针对一个文档的数组,您的方法确实很好,但这取决于OP的原始数据。我将检查两种方法的
explain
stat。如果我添加一个文本字段,这会崩溃,因为您已经进行了某种硬编码,这有助于
true
db.products.aggregate([
  {
    $match: {
      _id: 0,
      "sales_reps.is_doing_good": true
    }
  },
  { $unwind: "$sales_reps" },
  { $match: { "sales_reps.is_doing_good": true } },
  {
    $lookup: {
      from: "sales_rep_master",
      localField: "sales_reps.sales_rep_id",
      foreignField: "_id",
      as: "sales_reps"
    }
  },
  { $unwind: "$sales_reps" },
  { $addFields: { "sales_reps.doing_good": true } },
  {
    $group: {
      _id: "$_id",
      desc: { $first: "$desc" },
      name: { $first: "$name" },
      sales_reps: { $push: "$sales_reps" }
    }
  }
])
  {
    $group: {
      _id: "$_id",
      desc: { $first: "$desc" },
      name: { $first: "$name" },
      sales_reps: {
        $push: {
          $mergeObjects: [{ doing_good: true }, "$sales_reps"]
        }
      }
    }
  }
db.products.aggregate([
  {
    "$match": {
      "_id": 0
    }
  },
  {
    $addFields: {
      sales_reps: {
        $filter: {
          input: "$sales_reps",
          cond: {
            $eq: [ "$$this.is_doing_good", true]
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "sales_rep_master",
      "let": { "sr_id": "$sales_reps.sales_rep_id" },
      "pipeline": [
        {
          "$match": {
            "$expr": {
              "$and": [
                { "$in": [ "$_id","$$sr_id"] },
                // { other condition }
              ]
            }
          }
        },
        {
          "$addFields": {
            "doing_good": true
          }
        }
      ],
      "as": "sales_reps"
    }
  }
])