2015-02-23 43 views
0

对不起,如果这可能是一个典型的“RTM” - 问题,我是新来的MongoDB,并做了一些手动阅读,但很遗憾,我没有找到一个尝试解决这个问题。MongoDB:“查找()”与外键到不同的集合

我有两个集合,一个集合是“articles”,其中包含一个“categories”数组,其中包含一个或多个MongoID对象,其ID为我的类别集合。

我想显示所有类别与指向该类别的文章数量。下面我的解决办法,我发现atfer研发的一段时间:

我收藏的类别:

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类别,这是缓慢的,需要很多的时间。此外,我无法按照文章数量对我的分类进行分类,也无法遍历所有文章。

有没有更好的方法来做到这一点?

回答

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的是类_id的,你可以与categories集合连接变成名。不过,我认为你应该只在文章中保存类别名称_id。类别名称实际更改的频率如何?

但是,通常情况下,您应该避免进行这样的操作,因为聚合正在扫描每篇文章,将其展开为多个文档,并将每个文档处理为相应的组。最好在另一个集合中增量维护此信息例如,每次插入该类别的文章时,您都可以在每个类别文档中增加一个计数。

+0

非常感谢。即使这不是真正“我想听到的”,它似乎是唯一正确的信息,因为JOIN可以解决问题,但它们不在MongoDB中。我会用你的建议来实施一个计数器。感谢您的时间和信息。 – 2015-02-25 09:25:45