Разработка сайтов в Красном Лимане, ДНР. Как использовать поля данных JSON в базах данных MySQL

В моей статье «SQL vs NoSQL: различия «отмечалось, что грань между базами данных SQL и NoSQL становится все более размытой, поскольку каждый лагерь перенимает черты другого. Базы данных MySQL 5.7+ InnoDB и PostgreSQL 9.2+ напрямую поддерживают типы документов JSON в одном поле. В этой статье мы более подробно рассмотрим реализацию JSON в MySQL 8.0.

Обратите внимание, что любая база данных будет принимать документы JSON в виде одного строкового большого двоичного объекта. Однако MySQL и PostgreSQL поддерживают проверенные данные JSON в реальных парах ключ/значение, а не в простой строке.

Просто потому, что вы можете хранить JSON...

...из этого не следует, что вы должны.

Нормализация — это метод, используемый для оптимизации структуры базы данных. Правило первой нормальной формы (1NF) гласит, что каждый столбец должен содержать одно значение, что явно нарушается при хранении документов JSON с несколькими значениями.

Если у вас есть четкие требования к реляционным данным, используйте соответствующие поля с одним значением. JSON следует использовать с осторожностью в крайнем случае. Поля значений JSON не могут быть проиндексированы, поэтому избегайте их использования в столбцах, которые регулярно обновляются или просматриваются. Кроме того, меньше клиентских приложений поддерживают JSON, а технология новее, поэтому она может быть менее стабильной, чем другие типы.

Тем не менее, есть хорошие варианты использования JSON для редко заполняемых данных или пользовательских атрибутов.

Создайте таблицу с полем JSON

Рассмотрим магазин, торгующий книгами. Все книги имеют идентификатор, ISBN, название, издательство, количество страниц и другие четкие реляционные данные. Предположим, вы хотите добавить любое количество тегов категорий к каждой книге. Вы можете добиться этого в SQL, используя:

таблица тегов, в которой хранится имя каждого тега с уникальным идентификатором, и

таблица tagmap с записями „многие ко многим“, сопоставляющими идентификаторы книг с идентификаторами тегов

Это будет работать, но это громоздко и требует значительных усилий для второстепенной функции. Таким образом, вы можете определить поле tags JSON в таблице book вашей базы данных MySQL:

CREATE TABLE `book` (

`id` MEDIUMINT (8) UNSIGNED NOT NULL AUTO_INCREMENT,

`title` VARCHAR (200) NOT NULL,

`tags` JSON DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=INNODB;

Обратите внимание, что столбцы JSON не могут иметь значение по умолчанию, использоваться в качестве первичного ключа, использоваться в качестве внешнего ключа или иметь индекс. Вы можете создать вторичные индексы для сгенерированных виртуальных столбцов, но проще и практичнее сохранить значение в отдельном поле, если индексы требуются.

Добавление данных JSON

Целые документы JSON можно передавать в инструкциях INSERT или UPDATE. Например, теги нашей книги можно передать в виде массива (внутри строки):

INSERT INTO `book` (`title`, `tags`)

VALUES (

'ECMAScript 2015: A SitePoint Anthology’,

'[„JavaScript“, „ES2015“, „JSON“]'

) ;

JSON также может быть создан с помощью:

Функция JSON_ARRAY (), которая создает массивы. Например:

— returns [1, 2, „abc„]:

SELECT JSON_ARRAY (1, 2, 'abc’) ;

Функция JSON_OBJECT (), которая создает объекты. Например:

— returns {“a“: 1, „b“: 2}:

SELECT JSON_OBJECT ('a’, 1, 'b’, 2) ;

Функция JSON_QUOTE (), которая заключает строку в кавычки как значение JSON. Например:

— returns „[1, 2, \„abc\“]“:

SELECT JSON_QUOTE ('[1, 2, „abc“]') ;

или вы можете (CAST anyValue AS JSON).

Функция JSON_TYPE () позволяет вам проверять типы значений JSON. Он должен возвращать OBJECT, ARRAY, скалярный тип (INTEGER, BOOLEAN и т. д.), NULL или ошибку. Например:

— returns ARRAY:

SELECT JSON_TYPE ('[1, 2, „abc„]') ;

— returns OBJECT:

SELECT JSON_TYPE ('{“a“: 1, „b“: 2}') ;

— returns an error:

SELECT JSON_TYPE ('{„a“: 1, „b“: 2') ;

Функция JSON_VALID () возвращает 1, если JSON действителен, или 0 в противном случае:

— returns 1:

SELECT JSON_TYPE ('[1, 2, „abc„]') ;

— returns 1:

SELECT JSON_TYPE ('{“a“: 1, „b“: 2}') ;

— returns 0:

SELECT JSON_TYPE ('{„a“: 1, „b“: 2') ;

Попытка вставить недопустимый документ JSON вызовет ошибку, и вся запись не будет вставлена/обновлена.

Поиск данных JSON

Функция JSON_CONTAINS () принимает искомый документ JSON и другой документ для сравнения. Он возвращает 1, когда совпадение найдено. Например:

— all books with the 'JavaScript’ tag:

SELECT * FROM `book` WHERE JSON_CONTAINS (tags, '["JavaScript"]') ;

Аналогичная функция JSON_SEARCH () возвращает путь к заданному совпадению или NULL, если совпадений нет. Он передает искомый документ JSON, 'one’чтобы найти первое совпадение или 'all’найти все совпадения, и строку поиска (где%соответствует любое количество символов и _соответствует одному символу таким же образом, как и LIKE). Например:

— all books with tags starting 'Java’:

SELECT * FROM `book` WHERE JSON_SEARCH (tags, 'one’, 'Java%') IS NOT NULL;

Пути JSON

Путь JSON предназначен для значений и может использоваться для извлечения или изменения частей документа JSON. Функция JSON_EXTRACT () демонстрирует это, извлекая одно или несколько значений:

— returns „SitePoint“:

SELECT JSON_EXTRACT ('{„id“: 1, „website“: „SitePoint“}', '$.website’) ;

Все определения пути начинаются с символа $, за которым следуют другие селекторы:

точка, за которой следует имя, например$.website

[N]где N — позиция в массиве с нулевым индексом

подстановочный знак.[*]оценивает все члены объекта

подстановочный знак [*]оценивает все члены массива

подстановочный знак оценивается как prefix**suffixвсе пути, которые начинаются с именованного префикса и заканчиваются именованным суффиксом

Следующие примеры относятся к следующему документу JSON:

{

„a“: 1,

„b“: 2,

„c“: [3, 4],

„d“: {

„e“: 5,

„f“: 6

}

}

Примеры путей:

$.aвозвращается1

$.cвозвращается[3, 4]

$.c[1]возвращается4

$.d.eвозвращается5

$**.eвозвращается[5]

Извлечение путей JSON в запросах

Вы можете извлечь имя и первый тег вашей таблицы книг, используя запрос:

SELECT

title, tags→„$[0]“ AS `tag1`

FROM `book`;

В более сложном примере предположим, что у вас есть таблица пользователей с данными профиля JSON. Например:

я бы название профиль

1 Крейг { „электронная почта“: [„craig@email1.com“, „craig@email2.com“], „твиттер“: „@craigbuckler“ }

2 СайтПоинт { «электронная почта»: [], «твиттер»: «@sitepointdotcom» }

Вы можете извлечь имя Twitter, используя путь JSON. Например:

SELECT

name, profile→«$.twitter» AS `twitter`

FROM `user`;

Вы можете использовать путь JSON в предложении WHERE, чтобы возвращать только пользователей с учетной записью Twitter:

SELECT

name, profile→«$.twitter» AS `twitter`

FROM `user`

WHERE

profile→«$.twitter» IS NOT NULL;

Изменение части документа JSON

Существует несколько функций MySQL для изменения частей документа JSON с использованием обозначения пути. Это включает:

JSON_SET (doc, path, val[, path, val]...): вставляет или обновляет данные в документе

JSON_INSERT (doc, path, val[, path, val]...): вставляет данные в документ

JSON_REPLACE (doc, path, val[, path, val]...): заменяет данные в документе

JSON_MERGE (doc, doc[, doc]...): объединяет два или более документа

JSON_ARRAY_APPEND (doc, path, val[, path, val]...): добавляет значения в конец массива

JSON_ARRAY_INSERT (doc, path, val[, path, val]...): вставляет массив в документ

JSON_REMOVE (doc, path[, path]...): удаляет данные из документа

Таким образом, вы можете добавить «технический» тег к любой книге, в которой уже есть тег «JavaScript»:

UPDATE `book`

SET tags = JSON_MERGE (tags, '[»technical"]')

WHERE

JSON_SEARCH (tags, 'one’, 'JavaScript’) IS NOT NULL;

Дальнейшая информация

Руководство по MySQL предоставляет дополнительную информацию о типе данных JSON и связанных с ним функциях JSON.

Еще раз призываю вас не использовать JSON, если в этом нет крайней необходимости. Вы можете эмулировать всю ориентированную на документы базу данных NoSQL в MySQL, но это сведет на нет многие преимущества SQL, и вы с таким же успехом можете переключиться на настоящую систему NoSQL! Тем не менее, типы данных JSON могут сэкономить усилия для более неясных требований к данным в приложении SQL.

Делитесь нашими материалами с друзьями!

 

 

Заказать разработку сайта