mongodb - 根据用户偏好创建通知系统
问题描述
我正在尝试开发一个通知系统,但我不确定我是否正确地执行了某些部分。为了简化案例,我将使用一些通用命名。
系统应该如何工作:
- 注册用户可以根据从数据表网格中选择的过滤器订阅通知。(例如,当物品的数量为 X 时通知我,或者设置了多个过滤器,例如 set1.slug.quantity > X,some_value = false 和 some_int = 52)
我如何存储这些偏好:
示例对象
"O:8:"stdClass":2:{s:9:"set1.slug";a:1:{s:3:"$eq";s:10:"item_slug1";}s:13:" set1.quantity";a:1:{s:4:"$gte";i:1;}}"
生成简化
$object = new \stdClass();
$object->{'set1.slug'} = ['$eq' => 'item_slug1'];
$object->{'set1.quantity'} = ['$gte' => 1];
$object = serialize($object);
它还将 user_id 和从表单序列化的所有数据附加到部分 MongoDB 原始查询。
数据库存储对象 - 为用户设置的预定义过滤器。Md 是对象的 md5 哈希,以便于访问和编辑。
+----+-----------------------------------------------------------------------------------------------------------------+---------+----------------------------------+
| id | object | user_id | md |
+----+-----------------------------------------------------------------------------------------------------------------+---------+----------------------------------+
| 1 | O:8:"stdClass":2:{s:9:"set1.slug";a:1:{s:3:"$eq";s:10:"item_slug1";}s:13:"set1.quantity";a:1:{s:4:"$gte";i:1;}} | 22 | d5003ba3227c4db3189827329815b053 |
+----+-----------------------------------------------------------------------------------------------------------------+---------+----------------------------------+
这就是我将如何使用它——我对它如何工作的看法。
我会在 API 解析器中循环调用 findByFilterMD,同时填充表 Items。
// MongoDB query ( items database )
protected function executeUserFilter($array)
{
$list = Items::raw(function ($collection) use (&$array) {
return $collection->find(
$array, ["typeMap" => ['root' => 'array', 'document' => 'array']])
->toArray();
});
return $list;
}
// MySQL query - stored filters
protected function findByFilterMD($id)
{
$user = Auth::user();
$filter = PredefinedFilters::where('md', '=', $id)->first();
$deserialize = unserialize($filter->object);
$results = $this->executeUserFilter($deserialize);
// here would probably be a notification function like pusher or onesignal
}
我知道我实现这一目标的尝试可能是完全错误的,我可能会重新发明轮子,因为某些工具可能已经这样做了。
这是一个示例 Item MongoDB 对象
{
"_id": {
"$oid": "5c0406abdc04e7007f17f4ef"
},
"name": "myObject",
"inner_ID": "0db0b19a-9c01-4c21-8e10-6879dbcb37f1",
"some_value": false,
"some_int": 52,
"set1": [
{
"slug": "item_slug1",
"quantity": 88,
"extra": {
"value": 0
}
},
],
"set2": [
{
"slug": "item_slug2",
"quantity": 88,
"extra": {
"value": 0
}
},
{
"slug": "item_slug3",
"quantity": 88,
"extra": {
"value": 0
}
}
],
"expires": "2018-12-02 22:21:30"
}
我的问题来了
- 这种做法合适吗?
- 通知系统应该在哪里启动?我假设它可能在我解析项目 api 的地方,然后我应该遍历用户过滤器数据并运行存储的对象查询 - 或者它应该是一个用 cron 调用的单独系统?
我愿意接受任何建议,重新设计。
解决方案
我开发了一个类似这样的应用程序。我的方法是使用此处找到的 Laravel 通知: https ://laravel.com/docs/5.7/notifications#creating-notifications
假设在您的情况下,如果有人修改/创建数据,其他订阅用户将收到通知。
- 创建通知
php artisan make:notification UserUpdateQuantity
- 使用户模型可通知,还创建订阅某些内容的范围
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
public function scopeSubscribe($query)
{
return $query->where('subscribe', true);
}
}
$query
in 方法scopeSubscribe
需要根据你的业务逻辑进行调整
- 发送通知
$subscriber = User::subscribe()->get();
Notification::send($subscriber, new UserUpdateQuantity());
- 创建事件和监听器
你可以在这里找到事件和监听器https://laravel.com/docs/5.7/events
在 EventServiceProvider 中
protected $listen = [
'App\Events\QuantityUpdated' => [
'App\Listeners\SendUpdateQuantiryNotification',
],
];
然后运行命令php artisan event:generate
- 事件监听器
在事件监听器中,我们发送通知
public function handle(QuantityUpdated $event)
{
$subscriber = User::subscribe()->get();
Notification::send($subscriber, new UserUpdateQuantity());
}
- 雄辩的事件
在您的 eloquent 模型上添加事件,因此当有人更新数量时,它会触发事件,并且监听器会向订阅的用户发送通知
// In your model
protected $dispatchesEvents = [
'updated' => App\Events\QuantityUpdated::class
];
推荐阅读
- javascript - 用户输入未正确影响边框半径
- python - 选择总和为一个值同时最小化另一个值的最佳列
- javascript - Javascript异步函数返回承诺而不是实际值
- sql - For循环在R中迭代SQL查询
- api - 是否有完整的 Solr REST API 列表/文档?
- adb - 如何在android adb中访问当前和焦点窗口
- python-3.x - python不会解决我的方程式我该如何解决?
- mongodb - MongoDB 是否有数据存储限制
- sql - Oracle SQL 或 PLSQL 随负载扩展
- pyautogui - PyAutoGUI 错误尝试使用 pyautogui.press()