【问题标题】:Can I do case insensitive search with JSON_EXTRACT in MySQL?我可以在 MySQL 中使用 JSON_EXTRACT 进行不区分大小写的搜索吗?
【发布时间】:2018-09-21 18:17:12
【问题描述】:

我运行SELECT * FROM mytable WHERE LOWER(JSON_EXTRACT(metadata, "$.title")) = 'hello world' 的目的是让hello world 是来自用户的数据,我会将其展平为全小写。我的数据库中的实际值是“Hello World”,但这个搜索每次都返回空。

如果我使用SELECT LOWER(JSON_EXTRACT(metadata, "$.title")) FROM mytable,它肯定会返回小写字母hello world。不知道我在这里缺少什么。

获取实际值的查询:

SELECT JSON_EXTRACT(metadata, "$.title") FROM mytable 得到我"Hello World"

SELECT LOWER(JSON_EXTRACT(metadata, "$.title")) FROM mytable 让我"hello world"

试图找到正确行的查询

让我有价值

SELECT * FROM mytable WHERE JSON_EXTRACT(metadata, "$.title") = "Hello World"

SELECT * FROM mytable WHERE metadata->"$.title" = "Hello World"

SELECT * FROM ututs WHERE LOWER(metadata->"$.title") LIKE "%hello world%"

什么也得不到

SELECT * FROM mytable WHERE JSON_EXTRACT(metadata, "$.title") = "hello world"

SELECT * FROM mytable WHERE JSON_EXTRACT(metadata, "$.title") LIKE "%hello world%"

SELECT * FROM ututs WHERE LOWER(metadata->"$.title") = "hello world"

SELECT * FROM ututs WHERE LOWER(metadata->"$.title") LIKE "hello"

所以看起来结果是返回值,包括引号。不过,这似乎不是问题,因为我在匹配案例时得到了结果。我也很困惑为什么一开始的% 正在解决我的问题。 "H 之间没有空格。我自己输入了 JSON。

我还通过手动输入将metadata 列直接更新为{"title":"Hello World"}。 MySQL 会在冒号后自动添加一个空格以使其成为{"title": "Hello World"},这很好,但只是在检查任何空格。

【问题讨论】:

  • 将第二次查询的hello world结果复制并粘贴到第一次的where子句中,并使用模糊的like代替=。也许你的空白字符不一样?
  • 你确定SELECT LOWER(JSON_EXTRACT(metadata, "$.title")) FROM mytable只返回hello world,没有其他字符吗?如果hello world 只是返回值的一部分,那么您可能需要使用LIKE '%hello world%'。在您的问题中发布您的确切 JSON 字符串,以便我们更好地帮助您。
  • 试试JSON_UNQUOTE()->>
  • 根据您的 cmets 更新问题!

标签: mysql json


【解决方案1】:

SELECT * FROM mytable WHERE LOWER(JSON_EXTRACT(metadata, "$.title")) = JSON_QUOTE("hello world")SELECT * FROM mytable WHERE LOWER(metadata->"$.title") = JSON_QUOTE("hello world") 有效,但我不确定为什么在使用 LOWER 时需要使用 JSON_QUOTE 而不需要它进行精确搜索。

如果有人能解释原因,我很乐意将其标记为答案。

【讨论】:

  • 对于 MySQL JSON_QUOTED_STRING = "SIMPLE STRING", 但是 LOWER(JSON_QUOTED_STRING) != LOWER("SIMPLE STRING") 所以你可以降低(json_unquote(JSON)) = "value" 或降低(JSON) = JSON_QOUTE("值")
  • 这是因为 JSON_EXTRACT 返回双引号中的值(“hello world”),而 OP 提供的用于比较的值不在引号中(hell world)
【解决方案2】:

我使用like 遇到了类似的区分大小写的问题。 我通过将 JSON 函数的输出转换为 CHAR 来解决它。

This article 提到 JSON 函数返回 utf8mb4 string。这让我相信正在返回不同的数据类型(可能是字节数组)而不是VARCHAR。这可以解释为什么不区分大小写的文本搜索会失败。

select
json_unquote(json_extract(json, '$.reservation.status')) as status,
json_unquote(json_extract(json, '$.reservation.status')) like '%cancelled%' as case_sensitive,
cast(json_unquote(json_extract(json, '$.reservation.status')) as CHAR) like '%cancelled%' as case_insensitive
from myTable

这个查询的输出是:

|---------------------|------------------|---------------------|
|        status       |  case_sensitive  |  case_insensitive   |
|---------------------|------------------|---------------------|
|      Cancelled      |        0         |         1           |
|---------------------|------------------|---------------------|
|        New          |        0         |         0           |
|---------------------|------------------|---------------------|

【讨论】:

    【解决方案3】:

    使用column->>path获取数据:

    SELECT * FROM mytable 
    WHERE JSON_UNQUOTE(JSON_EXTRACT(metadata, "$.title")) LIKE  "%hello world%"
    
    OR
    
    SELECT * FROM mytable 
    WHERE metadata->>"$.title" LIKE  "%hello world%"
    

    不区分大小写

    SELECT * FROM mytable 
    WHERE LOWER(metadata->>"$.title") = "hello world"
    

    【讨论】:

    • ->> 无法解决区分大小写的问题:“MySQL 使用 utf8mb4 字符集和 utf8mb4_bin 排序规则处理 JSON 上下文中使用的字符串。”
    猜你喜欢
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 2013-09-26
    • 1970-01-01
    • 2013-07-08
    • 2012-12-20
    相关资源
    最近更新 更多