14

我有一个authors带有列的 MySQL 表idname并且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_booksJSON。但我只想要那些 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"
}
4

2 回答 2

10

目前还没有 JSON 函数可以使用类似“WHERE”的逻辑过滤文档或数组的元素。

但这是一些使用 JSON 数据的人可能想做的任务,因此 MySQL 提供的解决方案是使用JSON_TABLE() 函数将 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 数组仍然难以使用,即使使用JSON_TABLE(). 在此示例中,我将 公开tags为 JSON 数组,然后使用它JSON_SEARCH()来查找您想要的标签。

我同意 Rick James 的观点——您不妨将数据存储在规范化的表和列中。您认为使用 JSON 会为您节省一些工作,但事实并非如此。将数据存储为单个 JSON 文档而不是跨多个表的多行可能会更方便,但您只需再次解开 JSON,然后才能以您想要的方式查询它。

此外,如果您将数据存储在 JSON 中,则每次要查询数据时都必须解决这种JSON_TABLE()表达式。与正常存储数据相比,这将为您持续做更多的工作。

坦率地说,我还没有在 Stack Overflow 上看到一个关于在 MySQL 中使用 JSON 的问题,如果数据的结构不需要,我不会得出这样的结论:在关系表中存储数据比使用 JSON 更好。各不相同。

于 2019-02-18T23:14:11.470 回答
3

您正在向后处理任务。

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

结果是一个易于查询和快速的数据库。但是,它需要学习 RDBMS 和 SQL。

当数据是随机数据的集合时,JSON 很有用。您的 JSON 非常规则,因此数据非常适合 RDBMS 技术。在这种情况下,JSON 只是一种序列化数据的标准方式。但它不应该用于查询。

于 2019-02-18T18:58:09.880 回答