我的Elasticsearch索引中的每个文档都有两个包含用户ID的访问控制列表。一个是允许列表,另一个是拒绝列表。我正在尝试将过滤器添加到考虑这些ACL的给定查询中。我以为我可以对给定查询使用bool
子句must
子句,允许列表使用filter
子句,拒绝列表使用must_not
子句。到目前为止我所拥有的(用户1的例子):
{
"bool" : {
"must" : {
[given query]
},
"filter" : [ {
"match" : {
"acl.allow" : {
"query" : "/user/1",
"type" : "boolean"
}
}
}],
"must_not" : [ {
"match" : {
"acl.deny" : {
"query" : "/user/1",
"type" : "boolean"
}
}
}]
}
}
不幸的是,此查询未返回所需的结果。它返回未在其允许列表中列出用户1的对象(我不理解的行为)。此外,它(显然)忽略具有空访问控制列表的对象(任何人都应该可以看到)。有什么建议可以解决这个问题吗?
答案 0 :(得分:1)
我明白了。首先,由于其分析器,使用match
对于这种查询来说并不是一个很好的解决方案。使用term
让我感到困惑,为什么我没有得到任何结果。如果相应字段设置为not_analyzed
,则术语查询仅返回结果。因此我改变了我的映射:
"acl": {
"properties": {
"allow": {
"type": "string",
"index": "not_analyzed"
},
"deny": {
"type": "string",
"index": "not_analyzed"
}
}
}
我的第二个问题处理对象具有空ACL,对任何人都可见 - 使用exists
嵌套在must_not
嵌套在bool
中来解决。建议将其替换为已弃用的missing
查询。我的最终查询看起来像这样,并通过了我能想到的所有与ACL相关的测试。
{
"bool" : {
"must" : {
[given query]
},
"filter" : {
"bool" : {
"should" : [ {
"terms" : {
"acl.allow" : [ "/user/1" ]
}
}, {
"bool" : {
"must_not" : {
"exists" : {
"field" : "acl.allow"
}
}
}
} ]
}
},
"must_not" : {
"terms" : {
"acl.deny" : [ "/user/1" ]
}
}
}
}