1

抱歉,如果这可能是一个典型的“RTM”问题,我是 MongoDB 的新手并且做了一些手动阅读,但遗憾的是我没有找到解决这个问题的尝试。

我有两个集合,一个集合是“文章”,其中包含一组“类别”,其中包含一个或多个带有我的类别集合 ID 的 MongoID 对象。

我想显示所有类别以及引用该类别的文章数量。在我的解决方案下面,我发现了一些研究时间:

我的类别集合:

Array
(
    [_id] => MongoId Object
        (
            [$id] => 54eb1510974f5590179702aa
        )

    [name] => Test
    [multiplier] => 2    
)

我的文章集:

Array
(
    [_id] => MongoId Object
        (
            [$id] => 54e5e39f974f5535248b4bdf
        )

    [productnumber] => 63483

    [categories] => Array
        (
            //... other categories...
            [1] => MongoId Object
                (
                    [$id] => 54eb1510974f5590179702aa
                )

        )
    [image] => /var/www/mongodbtest/Files/FTP/images/63483.jpg
)

我当前的 PHP 代码:

foreach($oAllCategories as $oCategory)
{            
    $iArticleCount = $oArticles->find(array('categories' => $oCategory['_id']))->count();   
    // Debug
    echo $oCategory['name'].' = '.$iArticleCount.' <br />';
}  

现在的问题是,对于 70,000 篇文章和 2,200 个类别,这很慢并且需要很多时间。此外,如果不遍历所有文章,我无法按文章数量对我的类别进行排序。

有一个更好的方法吗?

4

1 回答 1

2

我不熟悉 PHP,所以我将使用 mongo shell 语法。您可以使用聚合管道一次性计算此服务器端:

db.articles.aggregate([
    { "$unwind" : "$categories" },
    { "$group" : { "_id" : "$categories", "count" : { "$sum" : 1 } } }
])

该阶段沿其数组$unwind“展开”每个文章文档,例如categories

{ "x" : 1, "categories" : ["a", "b", "c"] }
===>
{ "x" : 1, "categories" : "a" },
{ "x" : 1, "categories" : "b" },
{ "x" : 1, "categories" : "c" }

然后$group阶段将所有文档沿值合并categories并计算组中元素的数量。结果看起来像

{ "_id" : "c", "count" : 1 }
{ "_id" : "b", "count" : 1 }
{ "_id" : "a", "count" : 1 }

_id的 's 将是 category _id's,您可以将其与categories集合一起变成名称。不过,我认为您应该将类​​别名称与_id文章一起存储。类别名称实际上多久更改一次?

不过,一般来说,你应该避免做这样的操作,因为聚合是扫描每篇文章,将其扩展为多个文档,将每个文档处理到相应的组中。最好在另一个集合中以增量方式维护此信息 例如,每次插入该类别中的文章时,您可以在每个类别文档中增加一个计数。

于 2015-02-24T17:29:58.173 回答