【问题标题】:Making a Laravel 5.4 query on a JSON field containing a JSON array对包含 JSON 数组的 JSON 字段进行 Laravel 5.4 查询
【发布时间】:2018-06-09 12:51:00
【问题描述】:

我正在尝试查询包含值数组的 JSON 字段。 例如,我们将表命名为“User”和字段“Friends”。 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_CONTAINSJSON_SEARCHUser::whereRaw('JSON_CONTAINS(friends->"$.id", "3")')->get() 和许多不同的变体,但没有任何效果。

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

因此,如果有人可以帮助我解决这个问题,我将不胜感激。 旁注:我当前的 MySQL 版本是 5.7.11,所以它确实支持 JSON 字段并且 Laravel 不会抛出任何错误,它只是返回一个空数组。

【问题讨论】:

    标签: php mysql sql json laravel


    【解决方案1】:

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

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

    friends->"$[*].id" 选择器(它只是JSON_EXTRACT() 的快捷方式)将返回一个 ids 的 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

    【讨论】:

    • 你先生,让我很开心!非常感谢。 您的两种解决方案都有效,我可能会使用后一种,因为我发现它更优雅、更类似于 JSON,并且只需要一种 json 方法。再次感谢您非常直截了当但完整的回答。
    • 从 Laravel 5.6.24 开始,可以使用whereJsonContains():User::whereJsonContains('friends', ['id' => 3])->get();
    猜你喜欢
    • 2018-11-14
    • 1970-01-01
    • 2021-03-19
    • 2020-10-26
    • 1970-01-01
    • 2016-12-05
    • 2021-08-17
    • 2017-12-15
    • 2019-07-27
    相关资源
    最近更新 更多