mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 02:12:53 +00:00
perf: 优化消息搜索速度
This commit is contained in:
parent
b976f294f9
commit
287b6b396d
@ -147,18 +147,26 @@ class DialogController extends AbstractController
|
||||
}
|
||||
// 搜索消息会话
|
||||
if (count($list) < 20) {
|
||||
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id'])
|
||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||
->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
|
||||
->where('u.userid', $user->userid)
|
||||
->where('m.key', 'LIKE', "%{$key}%")
|
||||
->orderByDesc('m.id')
|
||||
$msgs = WebSocketDialogMsg::select(['web_socket_dialog_msgs.*'])
|
||||
->join('web_socket_dialog_msg_reads as r', 'r.msg_id', '=', 'web_socket_dialog_msgs.id')
|
||||
->where('r.userid', $user->userid)
|
||||
->where('r.live', 1)
|
||||
->where('web_socket_dialog_msgs.key', 'LIKE', "%{$key}%")
|
||||
->orderByDesc('r.msg_id')
|
||||
->take(20 - count($list))
|
||||
->get();
|
||||
$msgs->transform(function (WebSocketDialog $item) use ($user) {
|
||||
return $item->formatData($user->userid);
|
||||
});
|
||||
$list = array_merge($list, $msgs->toArray());
|
||||
foreach ($msgs as $msg) {
|
||||
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
|
||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||
->where('web_socket_dialogs.id', $msg->dialog_id)
|
||||
->first();
|
||||
if (empty($item)) {
|
||||
continue;
|
||||
}
|
||||
$item->search_msg_id = $msg->id;
|
||||
$item->last_msg = $msg;
|
||||
$list[] = $item->formatData($user->userid);
|
||||
}
|
||||
}
|
||||
//
|
||||
return Base::retSuccess('success', $list);
|
||||
|
||||
@ -200,7 +200,7 @@ class WebSocketDialog extends AbstractModel
|
||||
//
|
||||
if (isset($this->search_msg_id)) {
|
||||
// 最后消息 (搜索预览消息)
|
||||
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id);
|
||||
$this->last_msg = $this->last_msg ?? WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id);
|
||||
$this->last_at = $this->last_msg ? Carbon::parse($this->last_msg->created_at)->toDateTimeString() : null;
|
||||
} else {
|
||||
// 未读信息
|
||||
@ -214,11 +214,11 @@ class WebSocketDialog extends AbstractModel
|
||||
// 是否免打扰
|
||||
$this->silence = $this->silence ?? $dialogUserFun('silence');
|
||||
// 对话人数
|
||||
$this->people = WebSocketDialogUser::whereDialogId($this->id)->count();
|
||||
$this->people = $this->people ?? WebSocketDialogUser::whereDialogId($this->id)->count();
|
||||
// 有待办
|
||||
$this->todo_num = WebSocketDialogMsgTodo::whereDialogId($this->id)->whereUserid($userid)->whereDoneAt(null)->count();
|
||||
$this->todo_num = $this->todo_num ?? WebSocketDialogMsgTodo::whereDialogId($this->id)->whereUserid($userid)->whereDoneAt(null)->count();
|
||||
// 最后消息
|
||||
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first();
|
||||
$this->last_msg = $this->last_msg ?? WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first();
|
||||
}
|
||||
// 对方信息
|
||||
$this->pinyin = Base::cn2pinyin($this->name);
|
||||
|
||||
@ -200,6 +200,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
'msg_id' => $this->id,
|
||||
'userid' => $userid,
|
||||
'after' => 1,
|
||||
'live' => 1,
|
||||
]);
|
||||
if ($msgRead->saveOrIgnore()) {
|
||||
$this->send = WebSocketDialogMsgRead::whereMsgId($this->id)->count();
|
||||
@ -638,16 +639,35 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成关键词
|
||||
* @return string
|
||||
* 生成关键词并保存
|
||||
* @return void
|
||||
*/
|
||||
public function generateMsgKey()
|
||||
public function generateKeyAndSave(): void
|
||||
{
|
||||
return match ($this->type) {
|
||||
'text' => str_replace(" ", " ", strip_tags($this->msg['text'])),
|
||||
'meeting', 'file' => $this->msg['name'],
|
||||
default => '',
|
||||
};
|
||||
$key = '';
|
||||
switch ($this->type) {
|
||||
case 'text':
|
||||
case 'vote':
|
||||
case 'word-chain':
|
||||
$key = strip_tags($this->msg['text']);
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
$key = $this->msg['name'];
|
||||
$key = preg_replace("/^(image|\d+)\.(png|jpg|jpeg|webp|gif)$/i", "", $key);
|
||||
$key = preg_replace("/^LongText-(.*?)/i", "", $key);
|
||||
break;
|
||||
|
||||
case 'meeting':
|
||||
$key = $this->msg['name'];
|
||||
break;
|
||||
}
|
||||
$key = str_replace([""", "&", "<", ">"], "", $key);
|
||||
$key = str_replace(["\r", "\n", "\t", " "], " ", $key);
|
||||
$key = preg_replace("/^\/[A-Za-z]+/", " ", $key);
|
||||
$key = preg_replace("/\s+/", " ", $key);
|
||||
$this->key = trim($key);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -997,8 +1017,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
'modify' => $modify,
|
||||
];
|
||||
$dialogMsg->updateInstance($updateData);
|
||||
$dialogMsg->key = $dialogMsg->generateMsgKey();
|
||||
$dialogMsg->save();
|
||||
$dialogMsg->generateKeyAndSave();
|
||||
//
|
||||
WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($sender)->whereHide(1)->change([
|
||||
'hide' => 0, // 修改消息时,显示会话(仅自己)
|
||||
@ -1045,8 +1064,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
]);
|
||||
AbstractModel::transaction(function () use ($dialogMsg) {
|
||||
$dialogMsg->send = 1;
|
||||
$dialogMsg->key = $dialogMsg->generateMsgKey();
|
||||
$dialogMsg->save();
|
||||
$dialogMsg->generateKeyAndSave();
|
||||
//
|
||||
if ($dialogMsg->type === 'meeting') {
|
||||
MeetingMsg::createInstance([
|
||||
|
||||
@ -16,6 +16,7 @@ use Carbon\Carbon;
|
||||
* @property int|null $email 是否发了邮件
|
||||
* @property int|null $after 在阅读之后才添加的记录
|
||||
* @property int|null $dot 红点标记
|
||||
* @property int|null $live 是否在会话里
|
||||
* @property \Illuminate\Support\Carbon|null $read_at 阅读时间
|
||||
* @property-read \App\Models\WebSocketDialogMsg|null $webSocketDialogMsg
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
|
||||
@ -32,6 +33,7 @@ use Carbon\Carbon;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereDot($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereEmail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereLive($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMention($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMsgId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereReadAt($value)
|
||||
|
||||
@ -4,6 +4,7 @@ namespace App\Observers;
|
||||
|
||||
use App\Models\Deleted;
|
||||
use App\Models\WebSocketDialog;
|
||||
use App\Models\WebSocketDialogMsgRead;
|
||||
use App\Models\WebSocketDialogUser;
|
||||
|
||||
class WebSocketDialogObserver
|
||||
@ -39,6 +40,7 @@ class WebSocketDialogObserver
|
||||
public function deleted(WebSocketDialog $webSocketDialog)
|
||||
{
|
||||
Deleted::record('dialog', $webSocketDialog->id, $this->userids($webSocketDialog));
|
||||
WebSocketDialogMsgRead::whereDialogId($webSocketDialog->id)->update(['live' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,7 +51,9 @@ class WebSocketDialogObserver
|
||||
*/
|
||||
public function restored(WebSocketDialog $webSocketDialog)
|
||||
{
|
||||
Deleted::forget('dialog', $webSocketDialog->id, $this->userids($webSocketDialog));
|
||||
$userids = $this->userids($webSocketDialog);
|
||||
Deleted::forget('dialog', $webSocketDialog->id, $userids);
|
||||
WebSocketDialogMsgRead::whereDialogId($webSocketDialog->id)->whereIn('userid', $userids)->update(['live' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Deleted;
|
||||
use App\Models\WebSocketDialogMsgRead;
|
||||
use App\Models\WebSocketDialogUser;
|
||||
use Carbon\Carbon;
|
||||
|
||||
@ -29,6 +30,7 @@ class WebSocketDialogUserObserver
|
||||
}
|
||||
}
|
||||
Deleted::forget('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid);
|
||||
WebSocketDialogMsgRead::whereDialogId($webSocketDialogUser->dialog_id)->whereUserid($webSocketDialogUser->userid)->update(['live' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,6 +53,7 @@ class WebSocketDialogUserObserver
|
||||
public function deleted(WebSocketDialogUser $webSocketDialogUser)
|
||||
{
|
||||
Deleted::record('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid);
|
||||
WebSocketDialogMsgRead::whereDialogId($webSocketDialogUser->dialog_id)->whereUserid($webSocketDialogUser->userid)->update(['live' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -128,6 +128,7 @@ class WebSocketDialogMsgTask extends AbstractTask
|
||||
'mention' => $mention,
|
||||
'silence' => $silence,
|
||||
'dot' => $dot,
|
||||
'live' => 1,
|
||||
])->saveOrIgnore();
|
||||
$array[$userid] = [
|
||||
'userid' => $userid,
|
||||
|
||||
@ -26,11 +26,7 @@ class AddWebSocketDialogMsgsKey extends Migration
|
||||
\App\Models\WebSocketDialogMsg::chunkById(100, function ($lists) {
|
||||
/** @var \App\Models\WebSocketDialogMsg $item */
|
||||
foreach ($lists as $item) {
|
||||
$key = $item->generateMsgKey();
|
||||
if ($key) {
|
||||
$item->key = $key;
|
||||
$item->save();
|
||||
}
|
||||
$item->generateKeyAndSave();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
use App\Models\WebSocketDialog;
|
||||
use App\Models\WebSocketDialogMsg;
|
||||
use App\Models\WebSocketDialogMsgRead;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddWebSocketDialogMsgReadsLive extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
info("update web_socket_dialog_msg_reads live field");
|
||||
$isAdd = false;
|
||||
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) use (&$isAdd) {
|
||||
if (!Schema::hasColumn('web_socket_dialog_msg_reads', 'live')) {
|
||||
$isAdd = true;
|
||||
$table->integer('live')->nullable()->default(0)->index()->after('dot')->comment('是否在会话里');
|
||||
$table->index(['userid', 'live', 'msg_id']);
|
||||
}
|
||||
});
|
||||
info("update web_socket_dialog_msgs deleted_at");
|
||||
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
|
||||
$table->index('deleted_at');
|
||||
});
|
||||
if ($isAdd) {
|
||||
// 关键词包含
|
||||
$contains = [
|
||||
'您可以通过发送以下命令来控制我',
|
||||
'我的机器人。',
|
||||
'机器人名称:',
|
||||
'已加入的会话:',
|
||||
'你可以通过执行以下命令来请求我:',
|
||||
'假期类型:',
|
||||
'评论了此审批',
|
||||
'我是你的机器人助理',
|
||||
'打卡时间: ',
|
||||
'匿名消息使用说明',
|
||||
'匿名消息将通过',
|
||||
'导出任务统计已完成',
|
||||
'我不是你的机器人',
|
||||
'机器人名称由',
|
||||
'您没有创建机器人',
|
||||
'缺卡提醒:',
|
||||
'打卡提醒:',
|
||||
'文件下载打包已完成',
|
||||
'您有一个新任务 #',
|
||||
'您协助的任务 #',
|
||||
'您负责的任务 #',
|
||||
];
|
||||
info("update web_socket_dialog_msgs key contains");
|
||||
foreach ($contains as $key) {
|
||||
WebSocketDialogMsg::whereType('text')->where('key', 'like', "%{$key}%")->update(['key' => '']);
|
||||
}
|
||||
|
||||
// 关键词开始以
|
||||
$starts = [
|
||||
'/hello',
|
||||
'/help',
|
||||
'/list',
|
||||
'/info',
|
||||
'/newbot',
|
||||
'/setname',
|
||||
'/deletebot',
|
||||
'/token',
|
||||
'/revoke',
|
||||
'/webhook',
|
||||
'/clearday',
|
||||
'/dialog',
|
||||
'/api',
|
||||
];
|
||||
info("update web_socket_dialog_msgs key starts");
|
||||
foreach ($starts as $key) {
|
||||
WebSocketDialogMsg::whereType('text')->where('key', 'like', "{$key}%")->update(['key' => '']);
|
||||
}
|
||||
|
||||
// 关键词等于
|
||||
$equals = [
|
||||
'我要打卡',
|
||||
'IT资讯',
|
||||
'36氪',
|
||||
'60s读世界',
|
||||
'开心笑话',
|
||||
'心灵鸡汤',
|
||||
'使用说明',
|
||||
'隐私说明',
|
||||
'帮助指令',
|
||||
'API接口文档',
|
||||
'我的机器人',
|
||||
'清空上下文',
|
||||
'操作频繁!',
|
||||
'暂未开启签到功能。',
|
||||
'暂未开放手动签到。',
|
||||
'设置成功',
|
||||
'机器人不存在。',
|
||||
];
|
||||
info("update web_socket_dialog_msgs key equals");
|
||||
foreach ($equals as $key) {
|
||||
WebSocketDialogMsg::whereType('text')->whereKey($key)->update(['key' => '']);
|
||||
}
|
||||
|
||||
// 更新是否在会话里面
|
||||
info("update web_socket_dialog_msg_reads live value");
|
||||
WebSocketDialog::chunk(100, function ($dialogs) {
|
||||
/** @var WebSocketDialog $dialog */
|
||||
foreach ($dialogs as $dialog) {
|
||||
WebSocketDialogMsgRead::whereDialogId($dialog->id)->whereIn('userid', function ($query) use ($dialog) {
|
||||
$query->select('userid')->from('web_socket_dialog_users')->whereDialogId($dialog->id);
|
||||
})->update(['live' => 1]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user