люмен с mongodb: получение ошибки: вызов функции-члена prepare () для нуля - PullRequest
0 голосов
/ 16 ноября 2018

Я работаю с lumen и mongodb

Я хочу получить (общее количество непрочитанных) и общее количество сообщений на основе папки

мой запрос на mongodb похож на ниже,

$totalEmails = DB::connection('mongodb')
        ->select("sum(if(is_read==0,1,0)) as unread", "count(message_id) as total", "folder_id")
        ->collection('email_message')
        ->where('email_account_id', (int)$request->email_account_id)
        ->where('status', "Active")
        ->groupBy("folder_id")
        ->get();

выдает ошибку, как показано ниже,

FatalErrorException in Connection.php line 333:
Call to a member function prepare() on null

, пожалуйста, помогите мне решить эту проблему. Спасибо.

Я исправил эту ошибку, изменив свой запрос, как показано ниже,

$totalEmails = DB::connection('mongodb')            
            ->collection('email_message')
            ->select("sum(if(is_read==0,1,0)) as unread", "count(message_id) as total", "folder_id")
            ->where('email_account_id', (int)$request->email_account_id)
            ->where('status', "Active")
            ->groupBy("folder_id")
            ->get();

но это не дает мне ожидаемый результат,

это дает мне результат, как показано ниже,

[_id] => Array
            (
                [folder_id] => 5bee461e19f043020c001844
            )

    [folder_id] => 5bee461e19f043020c001844
    [sum(if(is_read==0,1,0)) as unread] => 
    [count(message_id) as total] => 

но мое ожидание

[_id] => Array
            (
                [folder_id] => 5bee461e19f043020c001844
            )

    [folder_id] => 5bee461e19f043020c001844
    [unread] => 2
    [total] => 10

Можете ли вы сказать мне, где неправильно в запросе ???

Если я использую запрос ниже

$totalEmails = DB::connection('mongodb')
    ->selectRaw("sum(if(is_read==0,1,0)) as unread", "count(message_id) as total", "folder_id")
    ->collection('email_message')
    ->where('email_account_id', (int)$request->email_account_id)
    ->where('status', "Active")
    ->groupBy("folder_id")
    ->get();

, это дает мне ошибку, как,

ErrorException in Builder.php line 245:
Argument 2 passed to Illuminate\Database\Query\Builder::selectRaw() must be of the type array, string given,

Если яЯ использую запрос ниже,

 $totalEmails = DB::connection('mongodb')        
        ->collection('email_message')
        ->selectRaw("sum(if(is_read==0,1,0)) as unread,count(message_id) as total,folder_id")
        ->where('email_account_id', (int)$request->email_account_id)
        ->where('status', "Active")
        ->groupBy("folder_id")
        ->get();

это дает мне результат как,

[_id] => Array
                (
                    [folder_id] => 5bee461e19f043020c001844
                )

            [folder_id] => 5bee461e19f043020c001844
            [sum(if(is_read==0,1,0)) as unread,count(message_id) as total,folder_id] => 

пожалуйста, помогите мне получить ожидаемый результат

Ответы [ 2 ]

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

Насколько мне известно, это довольно сложный запрос, который очень трудно выполнить с помощью методов laravel, поэтому я бы порекомендовал необработанный запрос, используя $aggregate, как в следующем примере:

$totalEmails = DB::connection("mongodb")
    ->collection("email_message")
    ->raw(function ($collection) {
        return $collection->aggregate(
            [
                [
                    "\$match" => [
                        "email_account_id" => (int)$request->email_account_id,
                        "status" => "active"
                    ]
                ],
                [
                    "\$group" => [
                        "_id" => [
                            "folder_id" => "\$folder_id"
                        ],
                        "unread" => [
                            "\$sum" => [
                                "\$switch" => [
                                    "branches" => [
                                        ["case" => [
                                            "\$eq" => [
                                                "\$is_read", '0,1,0'
                                            ]
                                        ],
                                            "then" => 1
                                        ]
                                    ],
                                    "default" => 0
                                ]
                            ]
                        ],
                        "total" => [
                            "\$sum" => 1
                        ]
                    ]
                ]
            ]
        );
    });

$collectedResult = array();
foreach ($result as $k => $v) {
    $collectResult[] = $v->jsonSerialize();
}

return $collectedResult;

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

Используя оператор raw, мы можем использовать функцию aggregate(), которая имитирует монго $aggregate.

Сначала мы хотим отфильтровать по email_account_id, что выполняется методом $match, обратите внимание, что $ экранирован, потому что в противном случае php будет интерпретировать его как переменную.

После этого нам нужно выполнить группу, с помощью которой делается эта часть:

"_id" => [
      "folder_id" => "\$folder_id"
]

Это создаст столбец _id с массивом с ключом folder_id и соберет все уникальные значения столбца DB «folder_id» в значение.

Таким образом, эта часть создаст массив элементов с уникальными значениями folder_ids, тогда непрочитанные и итоговые сообщения должны быть посчитаны для этих папок.

Все просто и выполняется с помощью оператора $sum. Непрочитанная часть немного сложнее, потому что для этого нужно отфильтровать оператор is_read. Это делается с помощью оператора switch и значения по умолчанию 0 (не учитывается при сбое условия).

Необработанный запрос вернет MongoCursor, поэтому последняя часть должна собрать эти результаты

Надеюсь, это поможет вам, и если что-то неясно, пожалуйста, дайте мне знать.

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

Я не уверен, что это является причиной вашей проблемы, но у вас есть ошибка в вашем коде

Это должно быть:

$totalEmails = DB::connection('mongodb')
    ->selectRaw("sum(if(is_read==0,1,0)) as unread, count(message_id) as total, folder_id")
    ->collection('email_message')
    ->where('email_account_id', (int)$request->email_account_id)
    ->where('status', "Active")
    ->groupBy("folder_id")
    ->get();

selectRaw необходимо включить необработанный кодв избранном.Вот документы для получения дополнительной информации

https://laravel.com/docs/5.5/queries#raw-expressions

...