MySQL поиск значения JSON по ключу в массиве - PullRequest
2 голосов
/ 23 апреля 2019

У меня есть массив объектов JSON, и я хочу получить определенный узел.Чтобы упростить мою проблему, допустим, что массив может выглядеть так:

[
    {"Race": "Orc", "strength": 14},
    {"Race": "Knight", "strength": 7},
    ...
]

И я хочу знать, например, силу рыцаря.Функция JSON_SEARCH возвращает путь '$[1].Race', и с помощью оператора path я мог бы получить силу.Есть ли способ объединить эти два, чтобы я мог сделать что-то вроде следующего?

SELECT someFunc(myCol,'$[*].Race','Orc','$.strength') AS strength
FROM myTable

Я использую MySQL 8.0.15.

Ответы [ 2 ]

2 голосов
/ 23 апреля 2019

По сути, вы хотите применить выделение и проекцию к элементам массива и полям объекта вашего документа JSON. Вам нужно сделать что-то вроде предложения WHERE, чтобы выбрать «строку» в массиве, а затем сделать что-то вроде выбора одного из полей (а не того, которое вы использовали в ваших критериях выбора).

Это делается в SQL с использованием предложения WHERE и SELECT-списка столбцов, но делать то же самое с JSON нелегко с помощью таких функций, как JSON_SEARCH () и JSON_CONTAINS ().

Решение, которое предоставляет MySQL 8.0, - это функция JSON_TABLE () , которая превращает документ JSON в виртуальную производную таблицу - как если бы вы определили обычные строки и столбцы. Это работает, если JSON в формате, который вы описываете, массив объектов.

Вот демонстрация, которую я сделал, вставив данные вашего примера в таблицу:

create table mytable ( mycol json );

insert into mytable set mycol = '[{"Race": "Orc", "strength": 14}, {"Race": "Knight", "strength": 7}]';

SELECT j.* FROM mytable, JSON_TABLE(mycol, 
  '$[*]' COLUMNS (
    race VARCHAR(10) PATH '$.Race', 
    strength INT PATH '$.strength'
  )
) AS j;
+--------+----------+
| race   | strength |
+--------+----------+
| Orc    |       14 |
| Knight |        7 |
+--------+----------+

Теперь вы можете делать то, что вы обычно делаете с запросами SELECT, например, выбор и проекцию:

SELECT j.strength FROM mytable, JSON_TABLE(mycol, '$[*]' 
  COLUMNS (
    race VARCHAR(10) PATH '$.Race', 
    strength INT PATH '$.strength'
  )
) AS j 
WHERE j.race = 'Orc'
+----------+
| strength |
+----------+
|       14 |
+----------+

У этого есть несколько проблем:

  1. Вам нужно делать это каждый раз, когда вы запрашиваете данные JSON, или создаете VIEW для этого.

  2. Вы сказали, что не знаете полей атрибутов, но чтобы написать запрос JSON_TABLE (), вы должны указать атрибуты, которые вы хотите найти и спроецировать в своем запросе. Вы не можете использовать это для полностью неопределенных данных.

Я ответил на множество похожих вопросов об использовании JSON в MySQL. Я заметил, что когда вы хотите сделать что-то подобное, обрабатывая документ JSON как таблицу, чтобы вы могли применить условие в предложении WHERE к полям в ваших данных JSON, тогда все ваши запросы становятся намного сложнее. Затем вы начинаете чувствовать, что вам лучше потратить несколько минут на определение ваших атрибутов, чтобы вы могли писать более простые запросы.

0 голосов
/ 23 апреля 2019

Посмотрите на JSON_CONTAINS (https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains)) и используйте его в предложении WHERE для определения записей, соответствующих вашим критериям.

...