我有一个"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');