首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用mongodb获取错误:在null上调用成员函数prepare()

用mongodb获取错误:在null上调用成员函数prepare()
EN

Stack Overflow用户
提问于 2018-11-16 05:12:52
回答 2查看 1.5K关注 0票数 2

我在和鲁门和mongodb合作

我希望根据文件夹获取(总未读)和总消息计数。

我的mongodb查询如下,

代码语言:javascript
复制
$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();

它给了我以下的错误,

代码语言:javascript
复制
FatalErrorException in Connection.php line 333:
Call to a member function prepare() on null

请帮我解决这个issue.thank你。

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

代码语言:javascript
复制
$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();

但这并没有给我预期的结果,

它给我的结果如下,

代码语言:javascript
复制
[_id] => Array
            (
                [folder_id] => 5bee461e19f043020c001844
            )

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

但我的期望是

代码语言:javascript
复制
[_id] => Array
            (
                [folder_id] => 5bee461e19f043020c001844
            )

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

你能告诉我查询哪里不对吗?

如果我使用下面的查询

代码语言:javascript
复制
$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();

它给了我一个错误,

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

如果我使用下面的查询,

代码语言:javascript
复制
 $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();

它给我的结果是,

代码语言:javascript
复制
[_id] => Array
                (
                    [folder_id] => 5bee461e19f043020c001844
                )

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

请帮我得到我的预期结果

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-16 11:09:32

据我所知,这是一个非常复杂的查询,而且很难用laravel方法生成,因此我建议使用$aggregate进行原始查询,如下面的示例所示:

代码语言:javascript
复制
$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语句,我们可以使用模拟mongo $aggregateaggregate()函数。

首先,我们希望在email_account_id上进行筛选,这是使用$match方法完成的,请注意,$是转义的,因为否则php会将其解释为变量。

在此之后,我们需要执行使用此部分完成的组:

代码语言:javascript
复制
"_id" => [
      "folder_id" => "\$folder_id"
]

这将创建带有键_id的数组的folder_id列,并将DB列'folder_id‘的所有唯一值收集到值中。

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

总数很简单,是用$sum操作符完成的。未读部分稍微复杂一些,因为这需要在is_read操作符上进行筛选。这是通过一个switch语句和默认值0完成的(条件失败时不要计算)。

原始查询将返回一个MongoCursor,所以最后一部分是收集这些结果。

我希望这对你有帮助,如果有什么不清楚的地方,请告诉我。

票数 0
EN

Stack Overflow用户

发布于 2018-11-16 05:26:52

我不确定这是否是导致您的问题的原因,但是您的代码中有一个错误。

它应该是:

代码语言:javascript
复制
$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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53331812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档