MySQL嵌套JSON列搜索并提取子JSON

时间:2017-11-30 05:56:53

标签: mysql mysql-5.7 mysql-json json-query

我有一个MySQL表authors,其中包含idnamepublished_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"
}

2 个答案:

答案 0 :(得分:4)

尚无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更好。不需要改变。

答案 1 :(得分:3)

您正在向后处理任务。

插入数据时进行提取。插入少量表(作者,书籍,标签,可能还有更多),并在它们之间建立关系。该数据库中不需要JSON

结果是易于查询且快速的数据库。但是,这需要了解RDBMS和SQL。

当数据是随机数据的集合时,

JSON很有用。您的JSON非常常规,因此 data 非常适合RDBMS技术。在这种情况下,JSON只是序列化数据的标准方法。但不应将其用于查询。