Laravel Eloquent 搜索 JSON 数组以获取特定列的值
Posted
技术标签:
【中文标题】Laravel Eloquent 搜索 JSON 数组以获取特定列的值【英文标题】:Laravel Eloquent search JSON array for a specific column's value 【发布时间】: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->'.$i-1.', 0)');
,但运气相同。
有什么想法吗? 提前致谢。
【问题讨论】:
根据documentation:“您可以使用whereJsonContains
查询JSON 数组。”由于您正在循环,您可以/应该使用普通的 where 查询,->where("readings->$i", '>', 0)
。
感谢@zoispag,但您的答案不起作用,尽管它不会引发任何错误。 $books
再次返回空。正如我所见,使用 JSON 的处理方式不同。
【参考方案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 你必须知道哪一栏是什么时候读的?我的查询将有效,但适用于所有书籍......而且,您需要在循环中做什么?你需要解释更多...以上是关于Laravel Eloquent 搜索 JSON 数组以获取特定列的值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Eloquent 在包含对象数组的 json 字段中进行搜索
在最近的关系记录中搜索 - Laravel (Eloquent)
Laravel/Eloquent 规范化 JSON 响应的关系?
Laravel Vue - 在 json 响应中获得 Eloquent