Laravel嵌套JSON数据查询问题:whereJsonContains查询失效排查
问题分析与解决方案
问题根源
你查询失败的核心原因是:transaction_details数组里的place字段存储的是JSON格式的字符串(带转义符的"{\"id\":3,...}"),而非原生的嵌套JSON对象。Laravel的whereJsonContains只能直接处理原生JSON结构,无法自动解析字符串形式的JSON内容。
解决方案
根据你的需求,分两种情况处理:
情况1:可以修改数据存储结构(推荐)
如果能调整数据存入方式,将place字段的JSON字符串解码为对象后再存入数据库(确保transaction_details里的place是原生JSON对象,而非字符串),之后即可使用你最初尝试的查询语句:
$q->whereJsonContains('history_product.transaction_details', ['place' => ['id' => 3]]);
情况2:无法修改存储结构,用原生SQL查询
直接利用MySQL的JSON函数来解析字符串并查询,通过whereRaw执行原生语句:
$q->whereRaw('EXISTS ( SELECT 1 FROM JSON_TABLE( history_product.transaction_details, "$[*]" COLUMNS ( place_str TEXT PATH "$.place" ) ) AS item WHERE JSON_UNQUOTE(JSON_EXTRACT(JSON_PARSE(item.place_str), "$.id")) = 3 )');
这段SQL的逻辑是:
- 用
JSON_TABLE把transaction_details数组拆分成单行记录 - 取出每个记录的
place字符串,用JSON_PARSE转成JSON对象 - 提取
id值并和3对比,存在匹配则返回该行数据
或者用更简洁的JSON_SEARCH写法:
$q->whereRaw('JSON_SEARCH( history_product.transaction_details, "one", "3", NULL, "$[*].place" ) IS NOT NULL');
注意:如果id是数值类型,需要把"3"改成3,并确保MySQL版本支持JSON_SEARCH的数值匹配(部分版本可能需要字符串形式)。
内容的提问来源于stack exchange,提问作者Roni Surya
相关产品推荐
相关产品推荐

