简体   繁体   English

使用 AND NOT CONTAINS (mysql 5.7) 查询 mysql json 列数组

[英]Query mysql json column array using AND NOT CONTAINS (mysql 5.7)

I have a table with a json column that contains an array of objects, like the following:我有一个包含一个对象数组的 json 列的表,如下所示:

create table test_json (json_id int not null primary key, json_data json not null) select 1 as json_id, '[{"category":"circle"},{"category":"square", "qualifier":"def"}]' as json_data union select 2 as json_id, '[{"category":"triangle", "qualifier":"xyz"},{"category":"square"}]' as json_data;
+---------+----------------------------------------------------------------------------------------+
| json_id | json_data                                                                              |
+--------------------------------------------------------------------------------------------------+
| 1       | [{"category":"circle"},   {"category":"square", "qualifier":"def"}]                    |
| 2       | [{"category":"triangle", "qualifier":"xyz"}, {"category":"square"}]                    |
+---------+----------------------------------------------------------------------------------------+

I'd like to be able to query this table to look for any rows ( json_id 's) that contain a json object in the array with both a "category" value of "square" and no "qualifier" property.我希望能够查询此表以查找数组中包含 json 对象的任何行( json_id ),其中“类别”值为“square”且没有“qualifier”属性。

The sample table above is just a sample and I'm looking for a query that would work over hundreds of rows and hundreds of objects in the json array.上面的示例表只是一个示例,我正在寻找一个可以处理 json 数组中数百行和数百个对象的查询。

In MySQL 8.0, you would use JSON_TABLE() for this:在 MySQL 8.0 中,您将为此使用 JSON_TABLE():

mysql> select json_id, j.* from test_json, json_table(json_data, '$[*]' columns (
    category varchar(20) path '$.category',
    qualifier varchar(10) path '$.qualifier')) as j 
  where j.category = 'square' and j.qualifier is null;
+---------+----------+-----------+
| json_id | category | qualifier |
+---------+----------+-----------+
|       2 | square   | NULL      |
+---------+----------+-----------+

It's not clear why you would use JSON for this at all.不清楚为什么要为此使用 JSON。 It would be better to store the data in the normal manner, one row per object, with category and qualifier as individual columns.最好以正常方式存储数据,每个对象一行,将categoryqualifier作为单独的列。

A query against normal columns is a lot simpler to write, and you can optimize the query easily with an index:针对普通列的查询编写起来要简单得多,您可以使用索引轻松优化查询:

select * from mytable where category = 'square' and qualifier is null;

I found another solution using only MySQL 5.7 JSON functions:我找到了另一个仅使用 MySQL 5.7 JSON 函数的解决方案:

select json_id, json_data from test_json 
where json_extract(json_data,
  concat(
    trim(trailing '.category' from 
      json_unquote(json_search(json_data, 'one', 'square'))
    ),
  '.qualifier')
) is null

This assumes the value 'square' only occurs as a value for a "category" field.这假定值 'square'作为"category"字段的值出现。 This is true in your simple example, but I don't know if it will be true in your real data.这在您的简单示例中是正确的,但我不知道在您的真实数据中是否会如此。

Result:结果:

+---------+------------------------------------------------------------------------+
| json_id | json_data                                                              |
+---------+------------------------------------------------------------------------+
|       2 | [{"category": "triangle", "qualifier": "xyz"}, {"category": "square"}] |
+---------+------------------------------------------------------------------------+

I still think that it's a CodeSmell anytime you reference JSON columns in a condition in the WHERE clause.我仍然认为,只要您在 WHERE 子句中的条件中引用 JSON 列,它就是CodeSmell I understood your comment that this is a simplified example, but regardless of the JSON structure, if you need to do search conditions, your queries will be far easier to develop if your data is stored in conventional columns in normalized tables.我理解您的评论,这是一个简化的示例,但无论 JSON 结构如何,如果您需要执行搜索条件,如果您的数据存储在规范化表的常规列中,您的查询将更容易开发。

Your request is not clear.你的要求不明确。 Both of your SQL records has not such properties but your JSON object has.你的两条 SQL 记录都没有这样的属性,但你的 JSON 对象有。 Maybe you try to find any record that has such object.也许您尝试查找任何具有此类对象的记录。 So the following is your answer:所以下面是你的答案:

create table test_json (json_id int not null primary key, json_data json not null) select 1 as json_id, '[{"category":"circle", "qualifier":"abc"},{"category":"square", "qualifier":"def"}]' as json_data union select 2 as json_id, '[{"category":"triangle", "qualifier":"xyz"},{"category":"square"}]' as json_data;
select * from test_json;
select * from test_json where 'square' in (JSON_EXTRACT(json_data, '$[0].category'),JSON_EXTRACT(json_data, '$[1].category'))
AND (JSON_EXTRACT(json_data, '$[0].qualifier') is NULL || JSON_EXTRACT(json_data, '$[1].qualifier') is NULL);

See Online Demo在线演示

Also see JSON Function Reference另请参阅JSON 函数参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM