Извините, если это типичный вопрос «RTM», я новичок в MongoDB и немного читал вручную, но, к сожалению, я не нашел попытки решить эту проблему.
У меня есть две коллекции, одна коллекция — это «статьи», содержащие массив «категорий», в котором есть один или несколько объектов 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 категориями это медленно и занимает много времени. Также я не могу сортировать свои категории по количеству статей, не просматривая все статьи.
Есть лучший способ сделать это?
Я не знаком с PHP, поэтому я буду использовать синтаксис mongo. Вы можете использовать конвейер агрегации для вычисления этой серверной стороны за один раз:
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
на статью, хотя. Как часто меняется название категории?
Как правило, вам следует избегать таких операций, как эта, потому что агрегация сканирует каждую статью, распределяет ее по нескольким документам и обрабатывает каждую в соответствующей группе. Лучше инкрементно хранить эту информацию в другой коллекции. Например, вы можете увеличивать счетчик в каждом документе категории каждый раз, когда вставляется статья в этой категории.
Других решений пока нет …