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"
}
}
])