新闻中心

Lar*el Eloquent 查询 JSON 数组中特定列的值

2025-11-14
浏览次数:
返回列表

laravel eloquent 查询 json 数组中特定列的值

本文深入探讨了在 Lar*el Eloquent 中查询 JSON 数组字段中特定索引值的问题。针对 `whereJsonDoesntContain` 和普通 `where` 方法在处理 JSON 数组路径时的局限性,提供了使用 `whereRaw` 结合 MySQL 的 `JSON_EXTRACT` 函数的有效解决方案。同时,文章也指出了 Lar*el 9.0 及更高版本对 JSON 数组路径查询的改进,为开发者提供了更简洁的语法。

理解 Lar*el Eloquent 查询 JSON 数组的挑战

在 Lar*el 应用中,将复杂数据结构(如数组)存储在数据库的 JSON 字段中是一种常见做法。然而,当需要查询 JSON 数组中特定索引位置的值时,开发者可能会遇到一些挑战。例如,假设我们有一个 Book 模型,其中包含一个 readings 字段,它是一个存储每月阅读次数的 JSON 数组,格式如下:[1, 0, 3, 2, 5, 5, 2, 1, 3, 0, 0, 2]。现在,我们希望筛选出特定月份阅读次数不为零的图书。

直观地,我们可能会尝试使用 Lar*el 提供的 whereJsonDoesntContain 或简单的 where 方法:

// 尝试使用 whereJsonDoesntContain
for ($i = 1; $i <= 12; $i++) {
    $books = Book::whereJsonDoesntContain('readings->'. $i - 1, 0)->get();
    // ...
}

// 尝试使用 whereRaw (与 whereJsonDoesntContain 内部实现类似)
for ($i = 1; $i <= 12; $i++) {
    $books = Book::whereRaw('not json_contains(readings->'.$i-1.', 0)')->get();
    // ...
}

// 尝试使用简单的 where
Book::where('readings->3', '!=', 0)->get();

然而,这些尝试可能无法返回预期的结果。问题在于 Lar*el 在内部将 readings->3 这样的路径转换为 $."3"。这种语法适用于查询 JSON 对象中的键,但不适用于 JSON 数组中的索引。对于 JSON 数组,正确的路径语法应该是$[3]`。

解决方案:使用 whereRaw 结合 JSON_EXTRACT

为了正确地查询 JSON 数组中的特定索引值,我们需要利用数据库底层的 JSON 函数。MySQL 提供了 JSON_EXTRACT 函数,它允许我们通过正确的路径语法提取 JSON 文档中的元素。结合 Lar*el 的 whereRaw 方法,我们可以构建出满足需求的查询:

use App\Models\Book;

// 循环遍历月份(0-11 代表一年中的12个月)
for ($i = 0; $i <= 11; $i++) {
    // 构建查询,使用 JSON_EXTRACT 提取指定索引的值,并检查其是否不等于0
    $books = Book::whereRaw("JSON_EXTRACT(`readings`, '\$[$i]') != 0")->get();

    // 在这里处理 $books 集合,例如:
    echo "Month " . ($i + 1) . " books with readings: " . $books->count() . "\n";
    foreach ($books as $book) {
        // var_dump($book->title);
    }
}

代码解释:

Perplexity Perplexity

Perplexity是一个ChatGPT和谷歌结合的超级工具,可以让你在浏览互联网时提出问题或获得即时摘要

Perplexity 302 查看详情 Perplexity
  • for ($i = 0; $i
  • Book::whereRaw(...): 允许我们直接写入原始的 SQL 查询条件。
  • JSON_EXTRACT(\readings`, '\$[$i]')`: 这是关键部分。
    • ``readings```: 是数据库表中的 JSON 列名。
    • '\$[$i]': 是 JSON_EXTRACT 函数的路径参数。
      • $ 表示 JSON 文档的根。
      • [ 和 ] 用于指定数组索引。
      • $i 是循环变量,代表当前的数组索引。
      • 请注意,由于 $i 是 PHP 变量,我们需要确保在 SQL 字符串中正确地拼接它。在双引号字符串中,$ 符号需要转义(\$),以避免 PHP 将其误认为是变量。
  • != 0: 检查提取出的值是否不等于 0。JSON_EXTRACT 返回的值通常是字符串形式,MySQL 会在比较时进行类型转换。

这个 whereRaw 查询会生成类似 SELECT * FROM books WHERE JSON_EXTRACT(readings, '$[0]') != 0 的 SQL 语句,从而正确地从 JSON 数组中筛选出符合条件的记录。

Lar*el 9.0 及更高版本的改进

值得注意的是,Lar*el 框架在 9.0 版本中对 JSON 数组路径的查询支持进行了改进。从 Lar*el 9.0 开始,whereJsonDoesntContain 等方法应该能够识别 readings->[3] 这样的数组路径语法。

// 适用于 Lar*el 9.0 及更高版本
Book::whereJsonDoesntContain('readings->[3]', 0)->get();

这意味着在较新版本的 Lar*el 中,开发者可以使用更简洁、更符合 Eloquent 风格的语法来查询 JSON 数组,而无需依赖 whereRaw。然而,对于使用旧版本 Lar*el 或需要兼容更广泛数据库环境的情况,whereRaw 结合 JSON_EXTRACT 仍然是可靠的通用解决方案。

注意事项与最佳实践

  1. 数据库版本兼容性: JSON_EXTRACT 和其他 JSON 函数在 MySQL 5.7+、PostgreSQL 9.3+ 等现代关系型数据库中得到支持。请确保您的数据库版本符合要求。
  2. 性能考虑: 对 JSON 字段进行查询,特别是涉及到 JSON_EXTRACT 等函数时,可能会比查询普通列的性能开销更大。数据库通常无法直接索引 JSON 字段的内部结构。如果您的应用需要频繁地查询 JSON 数组中的特定元素,并且数据量庞大,您可能需要考虑以下替代方案:
    • 冗余存储: 将需要频繁查询的 JSON 数组元素提取到单独的数据库列中。
    • 数据模型优化: 考虑将 JSON 数组中的每个元素建模为单独的关联表记录,实现数据规范化。例如,为每本书的每月阅读次数创建一个 book_readings 表。
  3. 路径转义: 在使用 whereRaw 构建 SQL 字符串时,务必注意路径中的特殊字符(如 $, [, ])的转义,以防止 SQL 注入或解析错误。在 PHP 的双引号字符串中,$ 需要用反斜杠转义。
  4. 类型转换: JSON_EXTRACT 返回的值通常是字符串。在进行比较操作时,数据库会尝试进行隐式类型转换。如果需要严格的类型比较,可以使用 CAST 或 CONVERT 函数显式转换类型。

总结

在 Lar*el Eloquent 中查询 JSON 数组的特定索引值,需要理解其底层 SQL 实现和路径语法。对于旧版 Lar*el 或需要通用解决方案的场景,通过 whereRaw 结合 JSON_EXTRACT 和正确的数组路径('$[index]')是高效且可靠的方法。对于 Lar*el 9.0 及更高版本,框架提供了更友好的 readings->[index] 语法支持,简化了开发流程。在选择查询策略时,应综合考虑数据库版本、性能需求和代码可维护性。

以上就是Lar*el Eloquent 查询 JSON 数组中特定列的值的详细内容,更多请关注php中文网其它相关文章!


# php  # laravel  # js  # json  # mysql  # 南宁专业的seo价格  # 小黄鱼营销推广  # 网站建设单页设计  # 亚马逊公司网站推广方式  # 武进网站关键词优化  # 侯马外贸品牌网站建设  # seo查询为空  # 手串营销推广广告图片高清  # 企业为什么要seo  # 山东网站推广找哪家  # 可以使用  # 特殊字符  # 正确地  # 您的  # 隐式  # 数据结构  # 适用于  # 多条  # 更高  # 组中  # 隐式类型转换  # ai  # app 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 探索高级语言到原生C/C++的转译:挑战与内存管理策略  中兴BladeV30怎样用测距估书架层高_iPhone中兴BladeV30测距估书架层高【家装参考】  wps文字怎么插入目录并自动更新_wps文字如何插入目录并自动更新方法  如何在J*a中实现统一对象行为接口_项目大型化时的接口规范化  QQ邮箱网页版入口登录 QQ邮箱在线邮箱官方通道  mysql备份恢复性能优化_mysql备份恢复性能优化方法  sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置  Win11怎么关闭快速启动_Win11彻底关机设置教程  必由学官方平台入口 必由学在线课堂登录地址  夸克浏览器网页版最新地址 夸克浏览器官方入口合集  网易大神账号申诉需要多久_网易大神账号申诉流程说明  Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址  J*aScript实现单选按钮与关联输入框的联动禁用教程  如何提高微信支付的安全性_微信支付安全防护与设置建议  Win11怎么开启高性能模式_Windows 11电源计划优化设置  c++如何使用TBB库进行任务并行_c++ Intel线程构建模块  Mac终端命令大全_Mac常用Terminal指令速查  解决 MongoDB 聚合查询中对象数组 _id 匹配问题  漫蛙manwa2最新登录网址_漫蛙manwa2手机网页版入口  J*aScript map 方法中处理循环元素为空数组的策略  Win11怎么设置开机NumLock亮 Win11修改注册表InitialKeyboardIndicators值  Go语言中Map值调用指针接收器方法的限制与应对  在J*a中如何捕获IndexOutOfBoundsException_索引越界异常防护方法说明  《刺客信条:影》PS5 Pro和Switch 2画面对比  Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量  J*a里如何使用N*igableMap进行导航操作_可导航Map操作技巧解析  在Qt QML中通过Python字典动态更新TextEdit内容的教程  163邮箱官方主页登录 直达网易邮箱登录核心页面  漫画星球免费下拉式入口 漫画星球免费漫画在线阅读网站  Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐  HTML转PPT成品工具有哪些?HTML网页转PPT成品工具大全  电脑安装程序提示“错误1722”怎么办_Windows Installer服务问题解决【教程】  LINUX的perf命令入门_LINUX官方性能分析工具的使用与解读  PDO预处理语句中冒号的正确处理:区分SQL函数格式与命名占位符  Tabulator表格日期时间排序问题及自定义解决方案  CSS Box Model与弹性按钮:维持布局稳定的动画实践  新三国志曹操传110级星符试炼夏侯渊极难攻略  微信网页版官方入口教程 微信网页版网页版快速登录步骤  AO3官方镜像站点汇总 AO3同人作品网页版直达链接  PHP中SSG-WSG API的AES加密实践:正确使用初始化向量  J*a编写用户注册与登录功能_掌握字符串与验证逻辑  韩剧圈正版入口页面_韩剧圈官网登录链接  电脑IP地址怎么查 查看本机IP地址的几种方法  Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】  微信网页版扫码登录入口 微信网页版二维码登录入口  12306选座如何查看座位示意图_12306座位示意图解读与使用  vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧  葱吃多了会怎样 葱吃多了会伤胃吗  QQ邮箱网页版邮箱入口 QQ邮箱官方登录平台  vivo手机互传视频怎么操作_vivo手机互传视频详细传输方法 

搜索