新闻中心

在 Lar*el Eloquent 中高效查询 JSON 数组字段的教程

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

在 Laravel Eloquent 中高效查询 JSON 数组字段的教程

本文旨在解决 lar*el eloquent 在查询 json 数组字段时遇到的路径解析问题。当需要根据 json 数组中特定索引的值进行筛选时,eloquent 的 `wherejsondoesntcontain` 或 `where` 方法可能因生成错误的 sql 路径(例如 `$."key"` 而非 `$[index]`)而失效。文章将详细解释此问题,并提供使用 `whereraw` 结合 `json_extract` 的有效解决方案,同时指出 lar*el 9.0 及更高版本对此的改进。

Lar*el Eloquent 查询 JSON 数组字段:问题与解决方案

在 Lar*el 应用开发中,我们经常会遇到需要存储和查询 JSON 类型数据的情况。Eloquent ORM 提供了便捷的方法来处理 JSON 字段,例如 whereJsonDoesntContain 或使用 -> 运算符直接访问 JSON 路径。然而,当 JSON 字段存储的是数组,并且我们需要根据数组的特定索引值进行筛选时,可能会遇到意料之外的行为。

问题描述:Eloquent 对 JSON 数组路径的误解

考虑一个 Book 模型,其中包含一个 readings 字段,该字段是一个 JSON 数组,记录了每个月书籍的阅读量,例如 [1, 0, 3, 2, 5, 5, 2, 1, 3, 0, 0, 2]。我们希望查询每个月中阅读量不为零(即有阅读量)的书籍。

直观上,我们可能会尝试使用 whereJsonDoesntContain 方法,如下所示:

for ($i = 1; $i <= 12; $i++) {
    // 尝试查询第 $i-1 个月阅读量不为0的书籍
    $books = Book::whereJsonDoesntContain('readings->'. ($i - 1), 0)->get();
    // ...
}

或者使用更通用的 where 方法:

for ($i = 1; $i <= 12; $i++) {
    $books = Book::where('readings->'. ($i - 1), '!=', 0)->get();
    // ...
}

然而,这些查询在实际执行时可能无法返回预期的结果。原因是 Lar*el 在内部将这些 Eloquent 调用转换为 SQL 查询时,对于 JSON 数组的索引路径处理存在偏差。

例如,Book::whereJsonDoesntContain('readings->3', 0) 会被转换为类似于以下 SQL 语句:

SELECT * FROM books WHERE NOT JSON_CONTAINS(`readings`, '0', '$."3"')

而 Book::where('readings->3', '!=', 0) 则会被转换为:

SELECT * FROM books WHERE JSON_UNQUOTE(JSON_EXTRACT(`readings`, '$."3"')) != '0'

问题在于 SQL 的 JSON 函数(如 JSON_CONTAINS 或 JSON_EXTRACT)在访问数组元素时,需要使用 $[index] 这样的路径格式,而不是 $."key"。Lar*el 默认将 -> 后面的数字视为对象键,导致生成的 SQL 路径不正确,从而无法准确查询 JSON 数组中的特定索引。

解决方案:使用 whereRaw 和 JSON_EXTRACT

为了正确地查询 JSON 数组的特定索引,我们需要绕过 Eloquent 自动生成的路径,直接使用 whereRaw 方法来构造 SQL 语句。通过 JSON_EXTRACT 函数,我们可以精确地指定数组元素的路径 $[index]。

Perplexity Perplexity

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

Perplexity 302 查看详情 Perplexity

以下是修正后的查询方法:

for ($i = 0; $i <= 11; $i++) { // 月份索引从0到11
    // 使用 whereRaw 和 JSON_EXTRACT 来查询指定月份阅读量不为0的书籍
    $books = Book::whereRaw("JSON_EXTRACT(`readings`, '\$[$i]') != 0")->get();
    // ...
}

代码解释:

  • for ($i = 0; $i
  • Book::whereRaw(...): 允许我们直接编写原始 SQL 条件。
  • JSON_EXTRACT(\readings`, '\$[$i]')`: 这是关键部分。
    • readings: 是你的 JSON 字段名。
    • '\$[$i]': 这是正确的 JSON 路径表达式。
      • \$: 在 PHP 字符串中,$ 需要转义,以确保它被视为 SQL 路径的一部分,而不是 PHP 变量。
      • [$i]: 表示访问 JSON 数组中索引为 $i 的元素。
  • != 0: 筛选出该月阅读量不为零的记录。

通过这种方式,生成的 SQL 语句将是正确的,能够准确地从 JSON 数组中提取指定索引的值进行比较。

注意事项与版本兼容性

  1. 数据库兼容性:JSON_EXTRACT 和 JSON_CONTAINS 等 JSON 函数是 MySQL 5.7+、PostgreSQL 9.4+ 等现代关系型数据库支持的特性。请确保你的数据库版本支持这些函数。

  2. 性能考量:对 JSON 字段进行查询通常会比查询普通列的性能开销大。如果查询频率高且数据量大,可以考虑将关键数据点提取为单独的列,或者为 JSON 字段创建合适的索引(例如,MySQL 8.0+ 支持 JSON 路径索引)。

  3. Lar*el 9.0+ 的改进:值得注意的是,Lar*el 9.0 及更高版本对 JSON 数组路径的处理进行了改进。从 Lar*el 9.0 开始,你可以通过以下语法正确地访问 JSON 数组元素:

    // 在 Lar*el 9.0+ 中,这将正确生成 $[3] 这样的路径
    Book::whereJsonDoesntContain('readings->[3]', 0);

    这意味着在较新版本的 Lar*el 中,你可能不再需要 whereRaw 来处理这种特定场景。然而,了解 whereRaw 的用法仍然是处理复杂或特定数据库函数查询时的重要技能。

总结

在 Lar*el Eloquent 中查询 JSON 数组字段的特定索引时,由于 Eloquent 早期版本对 JSON 路径解析的限制,直接使用 whereJsonDoesntContain 或 where 可能会生成错误的 SQL。通过 whereRaw 结合 JSON_EXTRACT 函数,并使用正确的 '$[index]' 路径语法,可以有效地解决这个问题。对于使用 Lar*el 9.0 及更高版本的开发者,框架本身已经对此进行了优化,提供了更简洁的语法支持。在选择解决方案时,应根据你的 Lar*el 版本和数据库兼容性进行权衡。

以上就是在 Lar*el Eloquent 中高效查询 JSON 数组字段的教程的详细内容,更多请关注php中文网其它相关文章!


# 转换为  # 长期推广营销策略  # 莆田在线推广网站  # 渌口区企业营销推广公司  # 永兴网站建设推广  # 网站后台建设管理  # seo引流教学  # 萍乡营销推广欢迎来电  # 关键词排名效果费用如何  # 推广口碑营销排名靠前  # 网络推广是不是营销策划  # 不为  # 怎么做  # 运算符  # mysql  # 这是  # 是一个  # 组中  # 的是  # 更高  # 多条  # 应用开发  # ai  # json  # js  # laravel  # php 


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


相关推荐: b站怎么看视频的弹幕数量_b站弹幕数量查看方法  树莓派传感器触发:通过Twilio API发送WhatsApp消息教程  PHP中SSG-WSG API的AES加密实践:正确使用初始化向量  Fabric模组开发:自定义物品与物品组的现代管理方法  Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】  必由学官网入口 必由学教师登录入口  微信网页版官方入口教程 微信网页版网页版快速登录步骤  Win10如何清理注册表垃圾 Win10手动清理无效注册表【技巧】  Angular Material 垂直步进器:实现底部到顶部排序的教程  mysql密码锁定怎么解锁_mysql密码锁定解锁后修改密码步骤  如何在J*a中使用Locale处理多语言环境  Node.js CSV 数据处理:基于字段值条件过滤整条记录的策略  QQ邮箱在线使用入口 QQ邮箱个人账号网页版登录  Go语言中JSON数据解析与字段访问教程  126邮箱手机版登录官网2026_126手机邮箱免费入口最新  TypeScript/J*aScript:高效查找数组中首个唯一ID对象  MAC如何安全彻底地删除文件_MAC使用终端命令确保文件无法被恢复  动漫花园资源网使用步骤_动漫花园资源网下载流程  不同用户不同价格! 索尼开启账户个性化定价测试  c++如何使用Meson构建系统_c++比CMake更快的构建工具  解决Python单元测试中Mock异常方法调用计数为零的问题  AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看  邮政快递单号查询入口 邮政快递物流信息在线查询入口  css绝对定位元素脱离父容器怎么办_确保父元素position非static  QQ邮箱在线登录平台 QQ邮箱个人邮箱网页版入口  Win11怎么查看电脑配置_Win11硬件配置检测工具使用  为什么我的微信朋友圈看不到别人的更新_微信朋友圈更新显示异常解决方法  如何将HTML表格多行数据保存到Google Sheets  cad如何更改注释性对象的比例_cad注释性比例调整方法  如何修改开机登录密码_Windows账户安全设置超详细教程【必学】  Go语言中Map存储的结构体如何调用指针方法:深入解析与实践  构建轻量级网站内部消息系统:Formspree 集成指南  凉拌黄瓜怎么拌更入味 凉拌黄瓜简单家常做法  抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩  css元素hover动画延迟生效怎么办_使用animation-delay调整触发时间  现代化 SciPy 一维插值:interp1d 的替代方案与最佳实践  解决Tabulator日期时间排序问题的专业指南  J*aScript教程:根据元素文本内容动态设置背景色  FullCalendar 自定义按钮样式定制指南  126邮箱网页版官方入口 126邮箱账号在线登录平台  批改网学生版PC登录 批改网官网登录系统入口  知音漫客官网漫画下载_知音漫客网页版阅读记录  谷歌学术网站直达地址 谷歌学术搜索网页版一键进入  电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】  J*aScript中高效管理与清空动态列表:避免循环陷阱  漫蛙漫画登录站点 漫蛙2正版漫画快速访问  AO3中文官网链接_AO3网页版稳定镜像站  汽水音乐车机版8.9下载 汽水音乐车机版8.9版本安装入口  夸克浏览器桌面版同步不了书签怎么处理 夸克浏览器跨设备同步异常解决方案  想当下一个《2077》?《心之眼》Steam评价升至"多半好评" 

搜索