很抱歉,如果这可能是一个典型的“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个类别,这很慢并且需要花费很多时间。此外,我不能按照文章的数量对我的类别进行排序,而不会遍历所有文章。
有更好的方法吗?
答案 0 :(得分: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
。类别名称实际更改的频率是多少?
通常,您应该避免执行此类操作,因为聚合扫描每篇文章,将其扩展为多个文档,将每个文档处理到相应的组中。最好在另一个集合中逐步维护此信息。例如,每次插入该类别的文章时,您都可以增加每个类别文档中的计数。