用Eloquent (Laravel)在小组前排序


Order By before Group By using Eloquent (Laravel)

我有一个"messages"表,包含以下列

CREATE TABLE `messages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `fromId` int(11) NOT NULL,
  `toId` int(11) NOT NULL,
  `message` text NOT NULL,
  `status` int(11) NOT NULL,
  `device` varchar(100) NOT NULL,
  `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1;

我试图得到所有的消息,其中'toId' = $id和分组fromId。问题在于,显示在搜索结果上的"信息"是最早的,而不是最新的。我试着通过createdAt订购,但它不起作用。

如何在查询和分组结果之前按"createdAt"排序?我想用Eloquent以一种简单的方式来完成这个任务。

我查询:

$chats = Message::with('sender','recipient')
        ->where('toId',$id)
        ->orderBy('createdAt')
        ->groupBy('fromId')
        ->paginate(10)

我只需要对消息模型做一些类似的事情。对我来说有效的是对返回的eloquent集合应用unique方法。

Model::where('toId', $id)
    ->orderBy('createdAt', 'desc')
    ->get()
    ->unique('fromId');

查询将返回按createdAt排序的所有消息,unique方法将为每个fromId减少到一条消息。这显然不如直接使用数据库的性能,但在我的情况下,我对查询有进一步的限制。

此外,还有许多更有用的方法来处理这些集合:https://laravel.com/docs/5.2/collections#available-methods

我找到了一个方法!基本上,创建一个子查询并在之前运行它,以便结果按预期排序,并在之后分组。

代码如下:

$sub = Message::orderBy('createdAt','DESC');
$chats = DB::table(DB::raw("({$sub->toSql()}) as sub"))
    ->where('toId',$id)
    ->groupBy('fromId')
    ->get();

试试这个查询:

$chats = Message::with('sender','recipient')
->where('toId',$id)
->whereRaw('id IN (select MAX(id) FROM messages GROUP BY fromId)')
->orderBy('createdAt','desc')
->paginate(10)

应该是这样的:

Message::whereToId($id)->groupBy('fromId')->latest('createdAt')->first();

看到添加的查询后,可能只需要向orderBy函数添加一个方向,如下所示:

$chats = Message::with('sender','recipient')
    ->select(DB::raw('*, max(createdAt) as createdAt'))
    ->where('toId',$id)
    ->orderBy('createdAt', 'desc')
    ->groupBy('fromId')
    ->paginate(10)

我的工作:(您可以通过createAt删除订单,以防createAt随id一起增加)

DB::select(DB::raw('select * from (select * from messages group by fromId desc) m order by m.createdAt'));
 $data = MCCAddMilkEntry::where('coming_from','=','society')
        ->whereRaw('id = (select max(`id`) from mcc_add_milk_entry)')->get();

@Sergio你的回答很好,但是如果有人想选择与....相关的模型呢?

答案:我已经测试了每一个功能,但我没有获得正确的数据。unique()给出了相关数组的数据。groupBy()给出了更好的但选择第一个消息。

最新收件箱消息的解决方案。我的情况:

$data = ChatMessage::where('incoming_msg_id', auth()->user()->id)->orWhere('outgoing_msg_id', auth()->user()->id)->latest('msg_id')->with('messageable')->get();
    $inbox = [];
    $itemIds = [];
    foreach ($data as $key => $value) {
        if (!in_array($value['messageable_id'].$value['msg_for'], $itemIds)) {
            array_push($inbox,$value);
            array_push($itemIds,$value['messageable_id'].$value['msg_for']);
        }
    }
    return $this->sendResponse($inbox,'Inbox');

你的情况:

$chats = Message::where('toId',$id)->orWhere('fromId', $id)->latest('id')->with('sender','recipient')->get();
    $inbox = [];
    $fromIds = [];
    foreach ($chats as $key => $value) {
        if (!in_array($value['fromId'], $fromIds)) {
            array_push($inbox,$value);
            array_push($fromIds,$value['fromId']);
        }
    }
    return $this->sendResponse($inbox,'Inbox');