在包含JSON数组的JSON字段上进行Laravel 5.4查询

问题描述 投票:5回答:1

我正在尝试查询包含值数组的JSON字段。例如,我们将表格命名为“用户”和“朋友”字段。以下是Friends字段的外观:

[{
    "id": 1,
    "img": "img-1.jpg",
    "name": "Name 1"
},
{
    "id": 2,
    "img": "img-2.jpg",
    "name": "Name 2"
},
{
    "id": 3,
    "img": "img-3",
    "name": "Name 3"
}]

所以我想要做的是在User表上查询来自Friends字段的所有内容,其中id等于3。

像这样的东西:User::where('friends->id', 3)->orderBy('id', 'desc')->get();当然,如果字段不包含数组,上面的例子可以很好地工作,所以如果它只是:

{
    "id": 1,
    "img": "img-1.jpg",
    "name": "Name 1"
}

绝望,尽管我知道这不合逻辑,但我尝试过“whereIn”:User::whereIn('friends->id', [3])->get()。或类似的东西:User::where('friends->[0]->id', 3)->get()User::where('friends->[*]->id', 3)->get()User::where('friends->*->id', 3)->get()

我也试过JSON_CONTAINS或JSON_SEARCH:User::whereRaw('JSON_CONTAINS(friends->"$.id", "3")')->get()和许多不同的变种,但没有做到这一点。

来到这里之前我已经阅读了一些有关此事的有趣文章(它们列在下面),但我似乎是唯一一个曾在MySQL数据库中存储过JSON数组的人,这怎么可能? ^^

所以,如果有人能帮我解决这个问题,我真的很感激。附注:我当前的MySQL版本是5.7.11,因此它支持JSON字段,而Laravel不会抛出任何错误,它只返回一个空数组。

php mysql sql json laravel
1个回答
11
投票

你的whereRaw尝试非常接近。如果您存储的是单个对象,那么您的路径将是$.id。但是,由于您要存储一组对象,因此您的路径为$[*].id。这应该适合你:

User::whereRaw('JSON_CONTAINS(friends->"$[*].id", "3")')->get();

friends->"$[*].id"选择器(它只是JSON_EXTRACT()的一个快捷方式)将返回一个id的json数组。然后JSON_CONTAINS()将检查json数组是否包含指定的id。

另一个选择是构建一个用于JSON_CONTAINS()的json搜索字符串。例如,此查询也应该起作用:

User::whereRaw('JSON_CONTAINS(friends, \'{"id": 3}\')')->get();

这避免了第一次调用JSON_EXTRACT(),所以你只调用一个json方法。我不知道哪个版本实际上会更快,或者是否会有任何差异。

此外,在与JSON_SEARCH()相关的旁注中,此功能仅在您搜索字符串值时才有效。由于你的json显示id表示为整数而不是字符串,JSON_SEARCH()将不起作用。 MySQL声称这是预期的行为(bug 79233dup bug 79316)。

仅供参考,here is the documentation for the json search methods

© www.soinside.com 2019 - 2024. All rights reserved.