Отфильтруйте ненужные поля из каждого объекта JSON массива JSON при чтении из MySQL - PullRequest
0 голосов
/ 27 апреля 2018

Допустим, в моей базе данных MySQL есть таблица с одним из столбцов типа JSON, и я сохранил следующий JSON в одной из записей

{
  "about": "person",
  "info": [
    {
      "fName": "John",
      "lName": "Booker",
      "sex": "male",
      "age": 20
    },
    {
      "fName": "Laurie",
      "lName": "Sparks",
      "sex": "female"
    },
    {
      "fName": "Adam",
      "lName": "Bate",
      "age": 26
    }
  ]
}

Можно ли как-нибудь извлечь следующее:

[
  {
    "sex": "male",
    "age": 20
  },
  {
    "sex": "female"
  },
  {
    "age": 26
  }
]

$.info[*] дает мне это

[
  {
    "fName": "John",
    "lName": "Booker",
    "sex": "male",
    "age": 20
  },
  {
    "fName": "Laurie",
    "lName": "Sparks",
    "sex": "female"
  },
  {
    "fName": "Adam",
    "lName": "Bate",
    "age": 26
  }
]

и $.info[*].sex и $.info[*].age дают мне эти данные соответственно

["male", "female"]

[20, 26]

Я думаю, я мог бы также получить следующее, но я не знаю, как

["male", "female", null]

[20, null, 26]

Исходный контекст проблемы

Приложение, с которым я сейчас работаю, сохраняет часть содержимого JSON в базе данных MySQL. Этот JSON может иметь определенные поля, значения которых представляют собой огромные изображения в кодировке Base64 Иногда мой клиент не заботится о получении этих изображений в кодировке Base64. Таким образом, чтобы повысить производительность, сократить объем данных, передаваемых из базы данных в мое приложение, и избежать обработки на стороне приложения, я хочу получить все поля в каждом элементе объекта JSON массива JSON, который не требует хранения этого огромного изображения. Информация.

Моя текущая реализация состоит в том, чтобы получить весь объект JSON из базы данных, а затем получить необходимые поля с помощью схемы JSON (вдохновленной этим проектом), но его производительность не соответствует ожидаемому SLA. Я действительно хочу выполнить как можно больше обработки данных на сервере MySQL, прежде чем помещать их в свое приложение и обрабатывать их, если в этом есть необходимость.

PS: я понимаю это; в отличие от чего-то вроде AWS S3; база данных может быть не лучшим вариантом для хранения больших документов JSON. Но я хочу использовать возможность пакетного чтения базы данных, которая может быть недоступна для других хранилищ данных NoSQL

1 Ответ

0 голосов
/ 28 апреля 2018

К сожалению, я не думаю, что это может быть сделано напрямую с помощью встроенных функций MySQL JSON (если бы JSON_REMOVE принимал пути подстановочных знаков, это могло бы быть). Однако это может быть достигнуто с помощью хранимой функции, подобной этой:

CREATE FUNCTION filter_json(j JSON) RETURNS JSON
BEGIN
  DECLARE n INT DEFAULT 0;
  DECLARE info, sex, age, data JSON;

  SET info = JSON_ARRAY();
  WHILE JSON_CONTAINS_PATH(j, 'one', CONCAT('$.info[', n, ']')) DO
    SET data = JSON_OBJECT();
    SET sex = JSON_EXTRACT(j, CONCAT('$.info[', n, '].sex'));
    IF sex IS NOT NULL THEN
       SET data = JSON_INSERT(data, '$.sex', sex);
    END IF;
    SET age = JSON_EXTRACT(j, CONCAT('$.info[', n, '].age'));
    IF age IS NOT NULL THEN
       SET data = JSON_INSERT(data, '$.age', age);
    END IF;
    SET info  = JSON_ARRAY_APPEND(info, '$', data);
    SET n = n + 1;
  END WHILE;
  RETURN info;
END

Для этого запроса:

SELECT filter_json('{ "about": "person", "info": [ { "fName": "John", "lName": "Booker", "sex": "male", "age": 20 }, { "fName": "Laurie", "lName": "Sparks", "sex": "female" }, { "fName": "Adam", "lName": "Bate", "age": 26 } ] }')

Вы получите желаемый результат:

[
  {"age": 20, "sex": "male"},
  {"sex": "female"}, 
  {"age": 26}
]
...