Laravel MongoDB - агрегирование, запрос заказа - PullRequest
0 голосов
/ 08 ноября 2018

Мне интересно, как я могу достичь определенного результата.

Начало Я использую https://github.com/jenssegers/laravel-mongodb

Пример кода , приведенный ниже, используется для получения массива документов, который содержит мой конкретный фрагмент в узле вознаграждений. И до этого момента все работает, как задумано.

 $array = [
            'rewards.slug' => ['$eq' => 'example_slug'],
            'expired' => ['$gte' => \Carbon\Carbon::now()->toDateTimeString()]
        ];
        $models = Master::raw(function ($collection) use (&$array) {
            return $collection->find(
                $array, ["typeMap" => ['root' => 'array', 'document' => 'array']])
                ->toArray();
        });

Мой пример документа

{
    "_id": {
        "$oid": "5be4464eafad20007245543f"
    },
    "some_int_value": 100,
    "some_string_value": "String",
    "rewards": [
        {
            "slug": "example_slug",
            "name": "Example slug",
            "quantity": 4,
            "estimated": {
                "value": 18750
            }
        },
        {
            "slug": "example_slug",
            "name": "Example slug",
            "quantity": 1,
            "estimated": {
                "value": 100
            }
        },
        {
            "slug": "other_example",
            "name": "Other slug example",
            "quantity": 1,
            "estimated": {
                "value": 100
            }
        }
    ],
    "expires": "2018-11-08 20:20:45",
}

Желаемый результат

Я бы хотел реализовать более сложный запрос, который бы выполнял следующие действия.

  • Получить документы, которые: псевдо select all documents that contain reward "slug": "example_slug", sum the quantity of them, return greater than X quantity documents, order by sum quantity desc
  • и очень похожий на вышеприведенный select all documents that contain reward "slug": "example_slug", sum estimated.value, return greater than X estimated.value documents, order by sum of estimated.value desc

Если вам нужно больше объяснений, не стесняйтесь спрашивать, я чувствую, что даже не знаю, с чего начать.

Вся помощь очень ценится

1 Ответ

0 голосов
/ 11 ноября 2018

Вы можете использовать ниже агрегации в 3,6.

$addFields для создания дополнительного поля slugcount для хранения результата.

$filter вознаграждение за сопоставление слагов example_slug, за которым следует $sum для суммирования поля quantity.

$match с $gt > X - выражение агрегации для фильтрации документов, в которых сумма всех совпадающих величин больше, чем X

$sort Slugcount desc и $project с исключением для удаления Slugcount из окончательного ответа.

db.colname.aggregate([
{"$addFields":{
  "slugcount":
   {"$let":{
    "vars":{
     "mslug":{
      "$filter":{
       "input":"$rewards",
       "cond":{"$eq":["$$this.slug","example_slug"]}
      }
     }
    },
    "in":{"$sum":"$$mslug.quantity"}
    }}
}}, 
{"$match":{"slugcount":{"$gt":X}}},
{"$sort":{"slugcount":-1}},
{"$project":{"slugcount":0}}
])

что-то вроде

ModelName::raw(function ($collection) {
 return $collection->aggregate([
  ['$match' => ['expired' => ['$gte' => \Carbon\Carbon::now()->toDateTimeString()]]],
  ['$addFields' => [
    'slugcount'
     ['$let' => [
      'vars' => [
       'mslug' => [
        '$filter' => [
         'input' => '$rewards',
         'cond' => ['$eq' => ['$$this.slug','example_slug']]
        ]
       ]
      ],
      'in' => ['$sum' => '$$mslug.quantity']
      ]]
  ]],
  ['$match' => ['slugcount'=> ['$gt' => X]]],
  ['$sort' => ['slugcount' => -1]],
  ['$project' => ['slugcount' => 0]]]);
});

Вы можете заменить quantity на estimated.value для второй агрегации.

...