需求 —— 字段内容权限
首先需要明白字段内容权限是什么。将 Elasticsearch 暂时当作数据库进行理解。假设数据库中有一张表格存储着国内的银行等金融企业的信息,表格包含企业名称、企业成立时间、企业董事长年龄等信息。对于所有查询该表格信息的用户,比如对用用户 1 ,希望他只能访问企业名为 "中国建设银行" 的信息,或者希望他只能访问企业成立时间在近10年内的企业。只能访问 "中国建设银行" 或 只能获取近10年成立的企业,这就是字段内容权限。
ES 布尔过滤器
ES 的过滤器在查询时,会做一个判断:是否应该将文档添加到结果集?通过这个判断,可以实现对用户的访问控制。
bool 过滤器由三部分组成:
{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
}
}
must:所有分句都必须匹配,与 AND 相同。
must_not:所有分句都必须不匹配,与 NOT 相同。
should:至少有一个分句匹配,与 OR 相同。
提示:bool 过滤器的每一个部分都是可选的(你可以只保留一个 must 分句),而且每一个部分可以包含一到多个过滤器。
ES 布尔过滤器示例
在显示查询中,可能希望过滤过个值或字段,例如希望在 Elasticsearch 中表达如下的 SQL 语句。
SELECT product
FROM products
WHERE (price = 20 OR productID = "XHDK-A-1293-#fJ3")
AND (price != 30)
希望过滤掉价格(price)为30的,而且价格为20的或者产品编号(productID)为 "XHDK-A-1293-#fJ3" 的产品。
结合 Elasticsearch 的 should 相当于 or,must_not 相当于 not,ES 表达上述 SQL 如下:
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}
上述代码中的 "term" 相当于精确匹配的意思。其含义是 "price" 这个字段精确匹配 20,"productID" 精确匹配 "XHDK-A-1293-#fJ3" 。相当于数学公式中的 "=" 符号的意思。
查询操作类型
如前面提到的 term 精确匹配,目前支持的查询操作类型为:term(精确匹配)、match(匹配)、match_phrase(短语匹配)、range(范围查询)。
term 精确匹配
term 对完全匹配的意思,对于数字类型的字段,就是单纯的 "=" 的关系,但对于字符串类型的字段而言,仅字段内容为不被分析时,才是等号的关系。
如一个索引定义如下,打入如下的数据:
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"full_text": {
"type": "string"
},
"exact_value": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
PUT my_index/my_type/1
{
"full_text": "Quick Foxes!",
"exact_value": "Quick Foxes!"
}
对于 Elasticsearch 而言,full_text 是被分析过的,索引中,该字段是[quick, foxes],而 exact_value 中存的则是 [Quick Foxes!]。
match 匹配查询
match 本质是只要内容包含任意查询关键字就匹配查询。用例子理解 match 较好理解,比如查询关键字是 "He is"。
GET /test/student/_search
{
"query": {
"match": {
"description": "He is"
}
}
}
对于 Elasticsearch 而言,关键字实际是 [he,is],字段 description 如下的都会匹配到。
"description": "He is passionate."
"description": "He is a big data engineer."
"description": "He works very hard because he wanna go to Canada."
"description": "She is so charming and beautiful."
实际就是只要包含任意一个关键字就可以了。
match_phrase 短语匹配
match_phrase 是短语匹配的意思。match 其只要包含任意查询关键字就匹配,但有时候希望字段包含和查询字段一模一样的内容。match_phrase 就是字段精确包含查询字段。
如上 match 的查询,如果采用 match_phrase 进行查询,就只有如下匹配:
"description": "He is passionate."
"description": "He is a big data engineer."
match_phrase 和 term 相比,前者是包含关系,后者是相等关系。
range 范围查询
range 比较好理解,就是满足一定范围的字段能够被查询出来。如最开始定义的用户仅能查询近10年的企业,就可以用 range 进行限定。
GET /test/student/_search
{
"query": {
"range": {
"established_time": {"gte": "10 years ago"}
}
}
}
字段内容权限的编写
上述说明都是为了正确的编写字段内容权限。
格式如下:
{
"and" : [],
"or" : [],
"not" : [],
}
为了让用户易于理解,采用 "and" 替换 "must"、 "or" 替换 "should"、 "not" 替换 "must_not"。
其中每一个 and、or、should等字段后的数组内容如下:
[
{"qt":"match_phrase","value":"工商银行"},
...
{"qt":"match_phrase","value":"建设银行"},
]
字段 "qt" 是查询操作类型,有 term(精确匹配)、match(匹配)、match_phrase(短语匹配)、rtd——range(范围查询)。
字段 "value" 是该字段查询类型的值。值得注意的是 rtd 的值是数字,一般为天。
如最初的金融企业信息表那样,希望用户不能查询招商银行的信息,则对于企业名(enterprise_name)这个字段。
字段权限内容编写为:
{
"not" : [{"qt":"match_phrase","value":"招商银行"}],
}
又如希望用户仅能查询成立时间(established_time)在90天内的企业信息,则对 "established_time" 字段的权限内容为:
{
"and" : [{"qt":"rtd","value":"90"}],
}
又如希望用户仅能查询查询企业名为中国银行、建设银行的,对 "enterprise_name" 字段的权限内容为
{
"or" : [{"qt":"match_phrase","value":"中国银行"},{"qt":"match_phrase","value":"建设银行"}],
}
字段内容权限验证 json shema
type: object
properties:
and:
type: array
minItems: 1
items:
type: object
required: [qt, value]
properties:
qt:
type: string
enum: ["term", "match", "match_phrase", "rtd"]
value:
type: string
maxLength: 255
additionalProperties: false
uiqueItems: true
or:
type: array
minItems: 1
items:
type: object
required: [qt, value]
properties:
qt:
type: string
enum: ["term", "match", "match_phrase", "rtd"]
value:
type: string
maxLength: 255
additionalProperties: false
uiqueItems: true
not:
type: array
minItems: 1
items:
type: object
required: [qt, value]
properties:
qt:
type: string
enum: ["term", "match", "match_phrase", "rtd"]
value:
type: string
maxLength: 255
additionalProperties: false
uiqueItems: true
additionalProperties: false