Извините за название, я не знаю, как лучше выразить проблему.
Я пытаюсь суммировать общее количество потраченных денег на книги в документе MongoDB. Это означает, что перед вычислением массива необходимо отфильтровать, что при расчете общей суммы потраченных денег учитываются только купленные книги.
Это пример документа (я удалил некоторые поля, чтобы он не стал слишком большим):
{
"_id" : ObjectId("598cb3f4ca693a0688004e2a"),
"title" : {
"de" : "Another",
"ja" : "アナザー",
"roomaji" : "Another"},
"total" : 4,
"volumes" : [
{
"volume" : 1,
"edition" : 1,
"price" : 7,
"releaseDate" : 1342051200,
"bought" : true,
"read" : true
},
{
"volume" : 2,
"edition" : 1,
"price" : 7,
"releaseDate" : 1347494400,
"bought" : true,
"read" : true
},
{
"volume" : 3,
"edition" : 1,
"price" : 7,
"releaseDate" : 1352419200,
"bought" : false,
"read" : false
},
{
"volume" : 4,
"edition" : 1,
"price" : 7,
"releaseDate" : 1357776000,
"bought" : false,
"read" : false
}
],
"releaseYear" : 2012
}
Итак, я хочу суммировать ценовое поле для всех объектов объема, но только для тех, для которых «куплено» установлено в значение «истина». В результате я хотел бы получить этот вывод:
{
"_id" : ObjectId(),
"title" : {
'de' : 'title'
},
"count" : 14
}
И это мой PHP-код
$result = $mongo->Book->aggregate([
[
'$group' => [
'_id' => '$_id',
'title' => ['$push' => '$title.de'],
'count' => [
'$sum' => [
'$map' => [
'input' => '$volumes',
'as' => 'vol',
'in' => [
'$cond' => [
[
'$eq' => ['$$vol.bought', true]
],
'$$vol.price',
0
]
]
],
]
]
]
],
[
'$sort' => [
'count' => -1
]
]
]);
Но count всегда возвращает 0. Что я делаю не так?
Он всегда возвращает 0, потому что $sum
оператор в $group
шаг конвейера ожидает выражение, которое оценивается в числовое значение, но здесь предоставленный $map
выражение оценивается в массив. Так же in
значение $map
оператор — это выражение, которое применяется к каждому элементу входного массива, который индивидуально ссылается на каждый элемент с именем переменной, заданным в as
следовательно, в качестве $cond
оператор здесь избыточен.
Вам нужно сначала отфильтровать массив, используя $filter
тогда вы можете отобразить элементы. К счастью для вашего случая $sum
Оператор может быть использован в $project
stage, так как возвращает сумму указанного списка выражений для каждого документа.
Попробуйте получить следующий конвейер, чтобы получить желаемый результат:
$result = $mongo->Book->aggregate([
[
"$project" => [
"title.de" => "$title.de",
"count" => [
"$sum" => [
"$map" => [
"input" => [
"$filter" => [
"input" => "$volumes",
"as" => "vol",
"cond" => "$$vol.bought"]
],
"as" => "el",
"in" => "$$el.price"]
]
]
]
],
[
'$sort' => [
'count' => -1
]
]
])
Других решений пока нет …