如何避免在运行php-mogodb聚合组函数时出现内存问题


How to avoid memory problems when running php mongodb aggregate group function?

当我试图按字段对列表进行分组时,遇到了内存问题。

输入:这是一个包含类别和一些字段的项目列表:

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

因此,基本上是直接在值上分组,而不是在"边界"上分组,因此在组合中产生唯一的值。