Как запросить значения полей MySQL JSON с помощью фильтра REST API с обратной связью

Какой правильный формат фильтра Loopback для запроса значения в поле MySQL (5.7) JSON? Например, как бы мы могли выполнить этот запрос с помощью Loopback-фильтра REST?

ЗАПРОС

SELECT name, info->"$.id", info->"$.team"
     FROM employee
     WHERE JSON_EXTRACT(info, "$.team") = "A"
     ORDER BY info->"$.id";

ДАННЫЕ ОБРАЗЦА

+---------------------------+----------
| info                      | name
+---------------------------+---------
| {"id": "1", "team": "A"}  | "Sam"  
| {"id": "2", "team": "A"}  | "Julie"
| {"id": "3", "name": "B"}  | "Rob"  
| {"id": "4", "name": "B"}  | "Cindy"
+---------------------------+---------

НЕУДАЧНЫЕ ПОПЫТКИ

/employee?filter[where][info->$.team]=A
/employee?filter[where][info.team]=A
/employee?filter[where][info][team]=A

person A2MetalCore    schedule 06.06.2016    source источник


Ответы (2)


Поскольку этот вопрос первым появляется из поиска Google и что коннектор mysql с обратной связью по-прежнему не позволяет выполнять запросы json, я чувствую, что будущим читателям следует дать правильный ответ.

Решение состоит в том, чтобы самостоятельно добавить эту функцию непосредственно в соединитель, пока политика обратной связи не остановится на решении о том, как на самом деле с этим справиться.

Вот наш вариант: поместите это в свою папку /connectors:

import * as connector from "loopback-connector-mysql"

var g = require('strong-globalize')();
var SqlConnector = require('loopback-connector').SqlConnector;
var ParameterizedSQL = SqlConnector.ParameterizedSQL;


const _buildExpression = connector.MySQL.prototype.buildExpression;

connector.MySQL.prototype.buildExpression = function (columnName, operator, operatorValue, propertyDefinition) {
  if (operator === 'json') {
    operatorValue = JSON.parse(operatorValue);
    const keys = Object.keys(operatorValue);
    if (keys.length > 1) {
      g.warn('{{MySQL}} {{json}} syntax can only receive one key, received ' + keys.length);
    }
    const jsonPointer = "$." + keys[0];
    const value = operatorValue[keys[0]];
    const column = `JSON_EXTRACT(${columnName}, "${jsonPointer}")`;
    if (value && value.constructor === Object) {
      // this includes another operator, apply it on the built column
      const operator = Object.keys(value)[0];
      return _buildExpression.apply(this, [column, operator, value[operator], propertyDefinition]);
    }
    const clause = `${column} = ?`;
    return new ParameterizedSQL(clause,
      [value]);
  } else {
    return _buildExpression.apply(this, [columnName, operator, operatorValue, propertyDefinition])
  }
};

export default connector;

Затем укажите этот файл в конфигурации вашей базы данных connector: 'connectors/mysql-json' или потребуйте его в коннекторе, если это не сработает (документ говорит, что мы можем определить путь, но нам не удалось заставить его работать ...)

Это довольно просто: мы перезаписываем функцию buildExpression, чтобы можно было вставить новый оператор json. Это позволит использовать его везде, где вы бы использовали другие операторы, такие как gt, lt, nin и т. Д.

Мы пошли еще дальше и разрешили передавать операторы в ваш оператор json, чтобы иметь возможность использовать их.

Вот пример фильтра запроса:

{"where":
   {
      "jsonProperty":{"json":{"id":1}}
   }
}
// Results in 
// WHERE JSON_EXTRACT('jsonProperty', '$.id') = 1



{"where":
   {
      "jsonProperty":{"json":{"id":{"gt":1}}}
   }
}
// Results in 
// WHERE JSON_EXTRACT(`jsonProperty`, '$.id') > 1

Мы просто добавляем ключ объекта, переданного в json, с $. для удобства использования (не уверен, что это лучший вариант, но работает для нас). Вы можете написать любой путь json в качестве ключа, просто опустите $.

person Salketer    schedule 10.08.2020
comment
Это выглядит интересно. Были ли у вас проблемы? Ищу аналогичное решение для наших экземпляров Loopback 3. Они хранят клиентские модели в json-объекте. - person user257980; 23.09.2020
comment
Пока это работало довольно хорошо. Нам пришлось внести некоторые коррективы, например, не добавлять $. автоматически для поддержки других синтаксисов и использования метода JSON, отличного от метода извлечения, такого как JSON_SEARCH, в зависимости от используемого оператора ... Кроме того, у нас были проблемы с преобразованием фильтра в [объект объекта] в некоторых запросах, оказывается, нам нужно использовать параметр allowExtendedOperators в противном случае оператор $ json не был разрешен должным образом, и свойство было согласовано с помощью toString () - person Salketer; 24.09.2020

Я не думаю, что на данный момент это возможно, я думаю, что ни один из коннекторов не поддерживает JSON_EXTRACT.

https://github.com/strongloop/loopback-connector-mysql

Я думаю, что для выполнения таких запросов вы можете использовать необработанные запросы и писать собственный код, используя фактический соединитель.

person Jaime Franco    schedule 07.06.2016