【问题标题】:Laravel Eloquent search JSON array for a specific column's valueLaravel Eloquent 搜索 JSON 数组以获取特定列的值
【发布时间】:2022-01-11 06:47:14
【问题描述】:

我有一个带有 readings (JSON) 字段的 Eloquent Book 模型。它是一个12个位置的数组,每个位置对应于当年每个月每本书的阅读次数,例如:

[1, 0, 3, 2, 5, 5, 2, 1, 3, 0, 0, 2]

在我的一个控制器中,我想按月选择所有具有一个或多个读数的书籍。所以我有一个for 循环,它会在几个月内迭代。以下是我的最佳尝试,但问题是 在任何迭代中 都没有选择任何书籍,尽管示例中的书籍应该在除 2、10 和 11 之外的所有迭代中返回:

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

我还尝试在 for 循环中使用 Book::whereRaw('not json_contains(readings-&gt;'.$i-1.', 0)');,但运气相同。

有什么想法吗? 提前致谢。

【问题讨论】:

  • 根据documentation:“您可以使用whereJsonContains 查询JSON 数组。”由于您正在循环,您可以/应该使用普通的 where 查询,-&gt;where("readings-&gt;{$i}", '&gt;', 0)
  • 感谢@zoispag,但您的答案不起作用,尽管它不会引发任何错误。 $books 再次返回空。正如我所见,使用 JSON 的处理方式不同。

标签: php json laravel eloquent


【解决方案1】:

看起来whereJsonDoesntContain 应该可以工作——它在内部使用JSON_CONTAINS——但它转换了这段代码:

Book::whereJsonDoesntContain('readings->3', 0);

进入这个查询:

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

问题在于路径无效; Laravel 假设传递的是对象键而不是数组键,其路径应类似于 $[3]

类似地,一个普通的where() 查询如下:

Book::where('readings->3', '!=', 0);

改为使用相同的无效路径。

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

所以我们剩下的是使用JSON_EXTRACT 的原始查询:

for ($i = 0, $i <= 11; $i++) {
    $books = Book::whereRaw("JSON_EXTRACT(`readings`, '\$[$i]') != 0");
}

这应该返回您需要的记录;这个查询的测试小提琴是here


注意这个语法:

Book::whereJsonDoesntContain('readings->[3]', 0);

应该可以工作in Laravel 9.0

【讨论】:

  • 谢谢@miken32,它成功了:)
【解决方案2】:

您的查询应该是:

$books = Book::whereJsonDoesntContain('readings', 0)->get();

删除for 或任何循环...readings 是字段,在本例中为1, 0, 3, 2, 5, 5, 2, 1, 3, 0, 0, 2...

【讨论】:

  • 我需要for 循环,因为除了$books 过滤之外,我还在循环中做一些其他事情...
  • 问题是寻找每个月读过的书,这只会返回每个月读过的书。
  • @miken32 这是真的,我的错
  • @andcl 你必须知道哪一栏是什么时候读的?我的查询将有效,但适用于所有书籍......而且,您需要在循环中做什么?你需要解释更多...
猜你喜欢
  • 2018-01-01
  • 2020-07-09
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 2022-08-09
  • 2013-11-20
  • 2019-11-05
相关资源
最近更新 更多