Laravel如何检查指定通知是否已存在?查询data字段报未知列错误
问题根因
你之前遇到的列不存在错误,本质是写法没有适配JSON字段的查询规则:notifications表的data是text类型,存储的是序列化后的JSON字符串,你写的data.id、data[id]这类语法,会被数据库直接当成一个独立的列名解析,不会去拆分data字段里的JSON结构,自然找不到对应列。
可用解决方法
最优写法(Laravel原生支持,适配主流数据库)
Laravel内置了对JSON字段查询的语法适配,只需要把点号替换为->标识JSON内部的键路径,框架会自动根据你使用的数据库类型,生成对应的JSON解析逻辑,不需要手写原生SQL:
$destination = User::findOrFail($model->user_id); // 用exists()替代count() > 0,只要查到匹配记录就终止扫描,查询效率更高 $previousNotification = $destination->notifications() ->where('data->id', $model->id) ->exists();
如果需要匹配更复杂的嵌套JSON结构,也可以直接用Laravel提供的whereJsonContains方法,效果一致:
$previousNotification = $destination->notifications() ->whereJsonContains('data', ['id' => $model->id]) ->exists();
低版本数据库临时兼容写法
如果你的数据库版本较低(比如MySQL 5.7以下,不支持原生JSON解析函数),可以用字符串模糊匹配临时实现,但存在误判风险:
$previousNotification = $destination->notifications() ->where('data', 'like', '%"id":' . $model->id . '%') ->exists();
注意:模糊匹配的精准度很差,比如查询id为
7的通知时,可能误匹配到JSON中id为17、77的记录,仅适合临时调试使用,不建议生产环境长期跑。
长期优化建议
当notifications表的数据量较大时,直接做JSON字段解析无法命中普通数据库索引,查询效率会随数据量上升明显下降。更稳妥的长期方案是:
- 给notifications表新增冗余字段(比如
related_target_id),创建通知时手动写入对应关联的模型id值 - 给该冗余字段建立数据库索引,后续查询直接用普通where条件匹配即可,性能远高于实时JSON解析
内容的提问来源于stack exchange,提问作者Alberto
相关产品推荐
相关产品推荐

