当我试图按字段对列表进行分组时,遇到了内存问题。
输入:这是一个包含类别和一些字段的项目列表:
{ category: "CATNAME1", field1: "value11", field2: "value21", ... },
{ category: "CATNAME2", field1: "value12", field2: "value22", ... },
{ category: "CATNAME3", field1: "value13", field2: "value23", ... },
{ category: "CATNAME4", field1: "value14", field2: "value24", ... }, ..
输出:应该是一个类别列表,每个类别都有一个相应项目的列表:
{ category: "CATNAME1", items: [
{ field1: "value12", field2: "value22", ... },
{ field1: "value14", field2: "value24", ... }, ..
] },
{ category: "CATNAME2", items: [
{ field1: "value12", field2: "value22", ... },
{ field1: "value14", field2: "value24", ... }, ..
] },
//编辑:为了更好的可读性,我们尝试了不同的版本,删除了除一个之外的所有版本。
部分解决方案:这适用于小列表,但当我有大约1000个类别,每个类别有1000个项目时,内存就会耗尽。:(
$cursor = $collection->aggregate(
array(
array(
'$match' => array(
.. some filters here ...
) ),
array(
'$group' => array(
'_id' => '$category',
'items' => array( '$addToSet' => array(
'field1' => '$field1',
'field2' => '$field2',
'field3' => '$field3',
'field4' => '$field4'
) ) ) ) ) );
当我试图从一开始就获得输入列表时,一切都很好。但当我试图将它们分组时,不知何故,它失败了。有什么想法为什么或如何修复它吗?
您的模式几乎是人们在SQL环境中使用的模式的精确副本。
尝试将您的模式更改为
{
"category": "cat1",
"values": {
"item1": "value1",
"item1": "value2"
}
}
只要不同键的数量不超过100或1000,这应该可以正常工作。
如前所述,错误的比赛,甚至错误的运动。为此使用聚合:
db.collection.aggregate([
{ "$group": {
"_id": "$category",
"name": { "$first": "$name" },
"value": { "$first": "$value" }
}
])
这是一个非常简单的查询。.group()
函数几乎应该被认为是弃用的。mapReduce
也不适合这种类型的操作,它运行的速度比聚合使用的本机代码接口慢得多。mapReduce
方法使用的JavaScript解释器的执行速度要慢很多倍。
编辑
如果您实际上只想在集合中使用唯一的值,那么该语句非常简单,就像在SQL:中一样
db.collection.aggregate([
{ "$group": {
"_id": {
"category": "$category",
"name": "$name",
"value": "$value"
}
}
])
因此,基本上是直接在值上分组,而不是在"边界"上分组,因此在组合中产生唯一的值。