Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.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_Aggregation Framework - Fatal编程技术网

Mongodb聚合管道大小和速度问题

Mongodb聚合管道大小和速度问题,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我尝试使用mongodb聚合查询联接($lookup)两个集合,然后对联接数组中的所有唯一值进行不同计数*注意:我不一定知道metaDataMap数组中有哪些字段(键)。我不想计算或包含地图中可能存在或不存在的字段。这就是为什么聚合查询看起来像这样 所以我的两个收藏看起来像这样:事件- { "_id" : "1", "name" : "event1", "objectsIds" : [ "1", "2", "3" ], } 物体 { "_id" : "1", "name" : "object1

我尝试使用mongodb聚合查询联接($lookup)两个集合,然后对联接数组中的所有唯一值进行不同计数*注意:我不一定知道metaDataMap数组中有哪些字段(键)。我不想计算或包含地图中可能存在或不存在的字段。这就是为什么聚合查询看起来像这样

所以我的两个收藏看起来像这样:事件-

{
"_id" : "1",
"name" : "event1",
"objectsIds" : [ "1", "2", "3" ],
}
物体

{
"_id" : "1",
"name" : "object1",
"metaDataMap" : { 
                     "SOURCE" : ["ABC", "DEF"],
                     "DESTINATION" : ["XYZ", "PDQ"],
                     "TYPE" : []
                }
},
{
"_id" : "2",
"name" : "object2",
"metaDataMap" : { 
                     "SOURCE" : ["RST", "LNE"],
                     "TYPE" : ["text"]
                }
},
{
"_id" : "3",
"name" : "object3",
"metaDataMap" : { 
                     "SOURCE" : ["NOP"],
                     "DESTINATION" : ["PHI", "NYC"],
                     "TYPE" : ["video"]
                }
}
我的结果是

{
_id:"SOURCE", count:5
_id:"DESTINATION", count: 4
_id:"TYPE", count: 2
}
到目前为止,我得到的是:

db.events.aggregate([
{$match: {"_id" : id}}

,{$lookup: {"from" : "objects",
        "localField" : "objectsIds",
        "foreignField" : "_id",
        "as" : "objectResults"}}

,{$unwind: "$objectResults"} //Line 1
,{$project: {x: "$objectResults.metaDataMap"}} //Line 2


,{$unwind: "$x"}
,{$project: {"_id":0}}

,{$project: {x: {$objectToArray: "$x"}}}
,{$unwind: "$x"}

,{$group: {_id: "$x.k", tmp: {$push: "$x.v"}}}

,{$addFields: {tmp: {$reduce:{
input: "$tmp",
initialValue:[],
in:{$concatArrays: [ "$$value", "$$this"]}
    }}
}}

,{$unwind: "$tmp"}
,{$group: {_id: "$_id", uniqueVals: {$addToSet: "$tmp"}}}

,{$addFields: {count: {"$size":"$uniqueVals"}}}
,{$project: {_id: "$_id", count: "$count"}}
]);
我的问题是我是否标记了第1行和第2行。上述方法可以工作,但对于metaDataMap数组字段(objectsResults.metaDataMap)中的25000个值,大约需要50秒。例如,在Object1 metaDataMap源数组中有25000个值。这就是放慢速度的方法。我的另一个更快的方法是将1号线和2号线替换为:

 ,{$project: {x: "$objectResults.metaDataMap"}} //Line 1
 ,{$unwind: "$x"} //Line 2
这要快得多(不到3秒),但只能在包含10000项或更少项的数据集上运行。任何更高的值,我都会得到一个错误,说“超过了最大文档大小”


请帮忙

如果您能够更改
对象
集合上的架构设计以包含
父id
字段,则可以立即删除管道的前4个阶段(第一个
$match
$lookup
$unwind
$project
)。这将使有关
第1行
第2行
的问题消失

例如,
对象
集合中的文档如下所示:

{
  "_id": "1",
  "name": "object1",
  "metaDataMap": {
    "SOURCE": [
      "ABC",
      "DEF"
    ],
    "DESTINATION": [
      "XYZ",
      "PDQ"
    ],
    "TYPE": [ ]
  },
  "parent_id": "1"
}
因此,您不需要昂贵的
$lookup
$unwind
。前4个阶段可替换为:

{$match: {parent_id: id}}
基于这个想法,我对管道进行了进一步优化,结果是:

db.objects.aggregate([
     {$match: {parent_id: id}}
    ,{$project: {metaDataMap: {$filter: {input: {$objectToArray: '$metaDataMap'}, cond: {$ne: [[], '$$this.v']}}}}}
    ,{$unwind: '$metaDataMap'}
    ,{$unwind: '$metaDataMap.v'}
    ,{$group: {_id: '$metaDataMap.k', val: {$addToSet: '$metaDataMap.v'}}}
    ,{$project: {count: {$size: '$val'}}}
])
这将输出:

{ "_id": "TYPE", "count": 2 }
{ "_id": "DESTINATION", "count": 4 }
{ "_id": "SOURCE", "count": 5 }

可以在“25000个不同数组中的项目”周围再添加一点描述吗?只是一个想法。可能您可以尝试将您的
metaDataMap
结构更改为
“metaDataMap”:[“k”:{“SOURCE”,“v”:[“ABC”,“DEF”]}…]
并在
$lookup
之后插入
$map
阶段。类似于
{“$project”:{“data”:{“$map”:{“input”:“$objectResults.metaDataMap”,“as”:{“$map”:{“input”:“$$resultom”,“as”:“resultim”,“in”:{“k”:“$$resultim.k”,“v”:{“$size”:“$$resultim.v”}}}}
。我相信这样你可以得到尺寸,退绕应该更快。但我不会得到一个与尺寸不同的计数。我会吗?我需要重复删除v值。