lumen with mongodb :getting error : Call to a member function prepare() on null

lumen with mongodb :getting error : Call to a member function prepare() on null

我正在使用流明和 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

请帮我解决这个issue.thank你

我已经通过如下更改查询解决了该错误,

$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] => 

请帮助我获得预期结果

我不确定这是否是导致您出现问题的原因,但您的代码有错误

应该是:

$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 才能在 select 中包含原始代码。这是更多信息的文档

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

据我所知,这是一个非常复杂的查询,很难用 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()函数来模拟mongo$aggregate.

首先我们要过滤 email_account_id,这是通过 $match 方法完成的,请注意 $ 被转义了,否则 php 会将其解释为变量。

之后我们需要执行这部分完成的分组:

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

这将创建 _id 列,其中包含一个包含键 folder_id 的数组,并将数据库列 'folder_id' 的所有唯一值收集到该值中。

因此这部分将生成一个具有唯一性的元素数组folder_ids,然后必须计算这些文件夹的未读邮件和总邮件数。

总数很简单,用$sum运算符完成。未读部分有点复杂,因为这需要在 is_read 运算符上进行过滤。这是通过 switch 语句和默认值 0 完成的(条件失败时不计算在内)。

原始查询将 return MongoCursor 所以最后一部分是收集这些结果

希望这对您有所帮助,如果有任何不清楚的地方,请告诉我。