如何使用环回RESTAPI过滤器查询MySQL JSON字段值

如何使用环回RESTAPI过滤器查询MySQL JSON字段值,mysql,rest,loopbackjs,strongloop,Mysql,Rest,Loopbackjs,Strongloop,在MySQL(5.7)JSON字段中查询值的正确环回过滤器格式是什么?例如,我们将如何使用环回REST过滤器执行此查询 查询 SELECT name, info->"$.id", info->"$.team" FROM employee WHERE JSON_EXTRACT(info, "$.team") = "A" ORDER BY info->"$.id"; 样本数据 +---------------------------+--------

在MySQL(5.7)JSON字段中查询值的正确环回过滤器格式是什么?例如,我们将如何使用环回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

我认为目前这是不可能的,我认为连接器都不支持JSON_提取


我认为,对于执行此类查询,您可以使用原始查询,并使用实际的连接器编写自定义代码。

我认为目前这是不可能的,我认为连接器都不支持JSON\u提取


我认为,为了执行这种查询,您可以使用原始查询,并使用实际的连接器编写自定义代码。

由于这个问题是Google search中第一个弹出的问题,而且环回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;
然后指向数据库配置连接器中的该文件:'connectors/mysql json',如果不起作用,则需要将其放入连接器中(doc说我们可以定义一个路径,但我们无法让它工作…)

这非常简单,我们覆盖
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路径作为键,只需ommit the
$。

因为这个问题是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;
然后指向数据库配置连接器中的该文件:'connectors/mysql json',如果不起作用,则需要将其放入连接器中(doc说我们可以定义一个路径,但我们无法让它工作…)

这非常简单,我们覆盖
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路径作为键,只需编辑
$。

这看起来很有趣。你有什么问题吗?正在为我们的环回3实例寻找类似的解决方案。他们将特定于客户的模型存储到json对象中。我们不得不做一些调整,比如不加美元。自动支持其他语法,并根据使用的运算符使用不同于类似提取的JSON_搜索的JSON方法。。。此外,我们在某些查询中将筛选器转换为[object object]时遇到问题,结果发现我们需要使用选项“allowExtendedOperators”,否则$json运算符没有正确解析,并且使用toString()对属性进行了一致性处理。这看起来很有趣。你有什么问题吗?正在为我们的环回3实例寻找类似的解决方案。他们将特定于客户的模型存储到json对象中。我们不得不做一些调整,比如不加美元。自动支持其他语法,并根据使用的运算符使用不同于类似提取的JSON_搜索的JSON方法。。。此外,我们在某些查询中将筛选器转换为[object object]时遇到问题,结果发现我们需要使用选项“allowExtendedOperators”,否则$json运算符没有正确解析,并且使用toString()对属性进行了一致性处理