简体   繁体   English

列出MySQL JSON字段的所有数组元素

[英]List all array elements of a MySQL JSON field

I have a JSON field to save post's tags. 我有一个JSON字段来保存帖子的标签。

id:1, content:'...', tags: ["tag_1", "tag_2"]

id:2, content:'...', tags: ["tag_3", "tag_2"]

id:3, content:'...', tags: ["tag_1", "tag_2"]

I just want to list all tags with their popularities (or even without them) something like this: 我只想列出所有标签的流行程度(甚至没有它们),如下所示:

tag_2: 3, tag_2:3,

tag_1: 2, tag_1:2,

tag_3: 1 tag_3:1

Here's the setup: 这是设置:

create table t ( id serial primary key, content json);
insert into t set content = '{"tags": ["tag_1", "tag_2"]}';
insert into t set content = '{"tags": ["tag_3", "tag_2"]}';
insert into t set content = '{"tags": ["tag_1", "tag_2"]}';

If you know the maximum number of tags in any tag array, you can extract all the tags using UNION: 如果您知道任何标记数组中的最大标记数,则可以使用UNION提取所有标记:

select id, json_extract(content, '$.tags[0]') AS tag from t 
union
select id, json_extract(content, '$.tags[1]') from t;

+----+---------+
| id | tag     |
+----+---------+
|  1 | "tag_1" |
|  2 | "tag_3" |
|  3 | "tag_1" |
|  1 | "tag_2" |
|  2 | "tag_2" |
|  3 | "tag_2" |
+----+---------+

You need as many unioned subqueries as the number of tags in the longest array. 您需要与最长数组中的标记数一样多的联合子查询。

Then you can put this in a derived table and perform an aggregation on it: 然后,您可以将其放在派生表中并对其执行聚合:

select tag, count(*) as count
from ( 
    select id, json_extract(content, '$.tags[0]') as tag from t 
    union 
    select id, json_extract(content, '$.tags[1]') from t
) as t2
group by tag
order by count desc;

+---------+-------+
| tag     | count |
+---------+-------+
| "tag_2" |     3 |
| "tag_1" |     2 |
| "tag_3" |     1 |
+---------+-------+

This would be easier if you stored tags in a second table instead of in a JSON array: 如果您将标记存储在第二个表而不是JSON数组中,这将更容易:

create table tags ( id bigint unsigned, tag varchar(20) not null, primary key (id, tag));
insert into tags set id = 1, tag = 'tag_1';
insert into tags set id = 1, tag = 'tag_2';
insert into tags set id = 2, tag = 'tag_3';
insert into tags set id = 2, tag = 'tag_2';
insert into tags set id = 3, tag = 'tag_1';
insert into tags set id = 3, tag = 'tag_2';

select tag, count(*) as count 
from tags
group by tag
order by count desc;

+-------+-------+
| tag   | count |
+-------+-------+
| tag_2 |     3 |
| tag_1 |     2 |
| tag_3 |     1 |
+-------+-------+

This solutions works no matter how many tags per id you have. 无论您拥有多少个标签,此解决方案都可以使用。 You don't need to know the max length of the list of tags per id. 您不需要知道每个ID的标记列表的最大长度。

JSON is nice when you need to store a 'document' of semi-structured data, but only when you treat the document as one irreducible data value. 当您需要存储半结构化数据的“文档”时,JSON很好,但只有当您将文档视为一个不可简化的数据值时。 As soon as you need to access elements of the document and apply relational operations to them, the document-oriented approach shows its weakness. 只要您需要访问文档的元素并对其应用关系操作,面向文档的方法就会显示其弱点。

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

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