MySQL 嵌套 JSON 列搜索和提取子 JSON
Posted
技术标签:
【中文标题】MySQL 嵌套 JSON 列搜索和提取子 JSON【英文标题】:MySQL nested JSON column search and extract sub JSON 【发布时间】:2018-05-13 23:41:49 【问题描述】:我有一个 mysql 表 authors
,其中包含 id
、name
和 published_books
列。在此,published_books
是一个 JSON 列。有样本数据,
id | name | published_books
-----------------------------------------------------------------------
1 | Tina |
| | "17e9bf8f":
| | "name": "Book 1",
| | "tags": [
| | "self Help",
| | "Social"
| | ],
| | "language": "English",
| | "release_date": "2017-05-01"
| | ,
| | "8e8b2470":
| | "name": "Book 2",
| | "tags": [
| | "Inspirational"
| | ],
| | "language": "English",
| | "release_date": "2017-05-01"
| |
| |
-----------------------------------------------------------------------
2 | John |
| | "8e8b2470":
| | "name": "Book 4",
| | "tags": [
| | "Social"
| | ],
| | "language": "Tamil",
| | "release_date": "2017-05-01"
| |
| |
-----------------------------------------------------------------------
3 | Keith |
| | "17e9bf8f":
| | "name": "Book 5",
| | "tags": [
| | "Comedy"
| | ],
| | "language": "French",
| | "release_date": "2017-05-01"
| | ,
| | "8e8b2470":
| | "name": "Book 6",
| | "tags": [
| | "Social",
| | "Life"
| | ],
| | "language": "English",
| | "release_date": "2017-05-01"
| |
| |
-----------------------------------------------------------------------
如您所见,published_books
列具有嵌套的 JSON 数据(一层)。 JSON 将动态 UUID 作为键,其值将作为 JSON 的书籍详细信息。
我想在特定条件下搜索books
,并单独提取那些书籍JSON数据作为结果返回。
我写的查询,
select JSON_EXTRACT(published_books, '$.*') from authors
where JSON_CONTAINS(published_books->'$.*.language', '"English"')
and JSON_CONTAINS(published_books->'$.*.tags', '["Social"]');
此查询执行搜索并返回整个 published_books
JSON。但我只想要那些 JSON 书。
预期的结果,
result
--------
"17e9bf8f":
"name": "Book 1",
"tags": [
"self Help",
"Social"
],
"language": "English",
"release_date": "2017-05-01"
-----------
"8e8b2470":
"name": "Book 6",
"tags": [
"Social",
"Life"
],
"language": "English",
"release_date": "2017-05-01"
【问题讨论】:
您找到解决方案了吗? 是否有充分的理由不存储标准化数据? @NicoHaase 旨在减少频繁的保存/更新查询。这只是一个示例,我们有一个复杂的大 JSON,我们将其转换为具有关系的对象,使用它并进行最终保存。使用该对象也很容易,因为它已经加载了相关的对象(存在于 JSON 本身中)。如果必须将其规范化为多个表,则保存/更新非常困难。这种方法专门针对我们的领域进行了优化。 @Yep_It's_Me,不。加载记录后,我在 Ruby 中过滤了结果 @MuhammadTahirQaiser 我找到了任何解决方案。加载记录后,我在 Ruby 中过滤了结果。 【参考方案1】:目前还没有 JSON 函数可以使用类似“WHERE”的逻辑过滤文档或数组的元素。
但这是一些使用 JSON 数据的人可能想做的任务,因此 MySQL 提供的解决方案是使用 JSON_TABLE() function 将 JSON 文档转换为一种格式,就像您将数据存储在普通格式中一样桌子。然后,您可以对返回的字段使用标准 SQL WHERE 子句。
你不能在 MySQL 5.7 中使用这个功能,但是如果你升级到 MySQL 8.0 你可以这样做。
select authors.id, authors.name, books.* from authors,
json_table(published_books, '$.*'
columns(
bookid for ordinality,
name text path '$.name',
tags json path '$.tags',
language text path '$.language',
release_date date path '$.release_date')
) as books
where books.language = 'English'
and json_search(tags, 'one', 'Social') is not null;
+----+-------+--------+--------+-------------------------+----------+--------------+
| id | name | bookid | name | tags | language | release_date |
+----+-------+--------+--------+-------------------------+----------+--------------+
| 1 | Tina | 1 | Book 1 | ["self Help", "Social"] | English | 2017-05-01 |
| 3 | Keith | 2 | Book 6 | ["Social", "Life"] | English | 2017-05-01 |
+----+-------+--------+--------+-------------------------+----------+--------------+
请注意,即使使用 JSON_TABLE()
,嵌套 JSON 数组仍然难以使用。在这个例子中,我将tags
暴露为一个JSON数组,然后使用JSON_SEARCH()
找到你想要的标签。
我同意 Rick James 的观点——您不妨将数据存储在规范化的表和列中。您认为使用 JSON 会为您节省一些工作,但事实并非如此。将数据存储为单个 JSON 文档而不是跨多个表的多行可能会更方便,但您只需再次解开 JSON,然后才能以您想要的方式查询它。
此外,如果您将数据存储在 JSON 中,您将不得不解决这种JSON_TABLE()
表达式每次您想要查询数据时。这将为您做更多的工作与您正常存储数据相比,持续进行。
坦率地说,我还没有在 Stack Overflow 上看到一个关于在 MySQL 中使用 JSON 的问题,如果数据的结构没有,我不会得出这样的结论:在关系表中存储数据比使用 JSON 更好。不需要改变。
【讨论】:
有人知道如何提取列标签上的值并将它们显示为:标签 ------ 自助社交【参考方案2】:你正在倒退。
在您插入数据时进行提取。插入少量表(作者、书籍、标签,也许还有更多)并在它们之间建立关系。 此数据库中不需要 JSON。
结果是一个易于查询和快速的数据库。但是,它需要学习 RDBMS 和 SQL。
当数据是随机数据的集合时,JSON 很有用。您的 JSON 非常规则,因此 data 非常适合 RDBMS 技术。在这种情况下,JSON 只是一种序列化数据的标准方式。但它不应该用于查询。
【讨论】:
这个答案告诉我们为什么爱迪生之前的人们烧油取光......,以不同的方式解决问题将我们带到这里,而不是坚持旧的解决方案。以上是关于MySQL 嵌套 JSON 列搜索和提取子 JSON的主要内容,如果未能解决你的问题,请参考以下文章