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
一起存储在文章中。类别名称实际上多久更改一次?
一般情况下,应该避免这样的操作,因为聚合是扫描每篇文章,将其扩展成多个文档,将每个文档处理到其对应的组中。最好在另一个集合中以增量方式维护此信息。例如,您可以在每次插入该类别中的文章时增加每个类别文档中的计数。
抱歉,如果这可能是一个典型的 "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
一起存储在文章中。类别名称实际上多久更改一次?
一般情况下,应该避免这样的操作,因为聚合是扫描每篇文章,将其扩展成多个文档,将每个文档处理到其对应的组中。最好在另一个集合中以增量方式维护此信息。例如,您可以在每次插入该类别中的文章时增加每个类别文档中的计数。