MongoDB: "find()" 与 foreign-key 不同 collection

MongoDB: "find()" with foreign-key to different collection

抱歉,如果这可能是一个典型的 "RTM" 问题,我是 MongoDB 的新手并且做了一些 manual-reading 但遗憾的是我没有找到解决该问题的尝试。

我有两个 collection,一个 collection 是 "articles" 包含一个 "categories" 的数组,它有一个或多个 MongoID objects,ID 为我的 categories-collection.

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

我的 collection 个类别:

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

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

我的 collection 篇文章:

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 个类别,这很慢并且需要花费大量时间。另外,如果不遍历所有文章,我就无法按文章数量对类别进行排序。

有更好的方法吗?

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

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

$unwind 阶段 "unwinds" 每篇文章沿其 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 属于 _id 类别,您可以将其加入 categories 集合以生成名称。不过,我认为您应该将类​​别名称与 _id 一起存储在文章中。类别名称实际上多久更改一次?

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