以下是我的内容模型。

文档与用户和组ACL相关联,这些用户和组ACL定义了有权访问文档的主体。
该文档本身是一堆元数据和一个庞大的内容主体(从pdfs / docs等中提取)。

执行搜索的用户必须仅限于他/她有权使用的文档集(由文档上的ACL定义)。由于用户acls或由于用户所属的组,他/她可以访问文档。
文档中的组成员身份和ACL本质上都是高度 transient 的,这意味着用户的组成员身份会经常更改,文档本身上的ACL也经常更改。

方法1
将acl和它的元数据一起存储在文档中,作为未存储的字段。将ACL中的组扩展到单个用户(因为acl可以是一个组)。
在查询时,将过滤器附加到用户查询,该查询将进行 bool(boolean) 过滤,以仅在acl字段中包含具有用户ID的文档

"filter" : {
        "query" : {
            "term": {
                "acls": "1234"
            }
        }
      }

我看到的这种方法的问题是,尽管文档元数据/内容未更改,但文档仍需要重新编制索引。

每次用户的组成员身份更改
每次文档上的ACL更改(文档的权限更改)

我假设这将导致大量的段创建和合并,尤其是因为文档主体(文档的字段之一)是一个很大的文本部分。

方法二:
这是对方法1的修改。当更新严格与acl相关时,此方法尝试限制文档上的更新。

而不是在元数据上定义ACL。这种方法需要创建多种类型

文档索引中
Document (with metadata & text body) as a parent

id
text


userschild Document (parent id & user acls only). This document will exist for each parent

id
parentid
useracls



groupschild Document (parent id & group acls only). This document will exist for each parent with group acls

id
parentid
groupacls

用户索引中
系统中每个用户与他/她相关联的组的条目
User
   id
   groups

这里的想法是,现在将更新本地化到不同的ElasticSearch实体。
如果发生用户acl更改,则只会更新userschild文档(避免对父文档进行可能昂贵的更新)。
在更改组acl的情况下,只会更新groupschild文档(再次避免在父文档上进行潜在的昂贵更新)。
如果用户组成员身份再次发生更改,则只有二级索引将得到更新(避免在父文档上进行更新)。

查询本身将如下所示。
   "filter" : {
            "query" : {
               "bool": {
                 "should": [
                   {
                      "has_child": {
                        "type": "userschild",
                        "query": {
                          "term": {
                            "users": "1234"
                          }
                        }
                      }
                    },{
                      "has_child": {
                        "type": "groupschild",
                        "query": {
                        "terms" : {
                          "groups" : {
                            "index" : "users",
                            "type" : "user",
                            "id" : "1234",
                            "path" : "groups"
                          }
                        }
                      }
                      }
                    }
                 ]
               }
            }
          }

由于要涉及的查询的性质,我对其可扩展性有疑问。它涉及两个术语查询,其中之一必须从单独的索引中构建。我正在考虑使用启用了docvalue的字段来改善术语查找。

方法2会扩展吗?我关心的是有关has_child查询及其可伸缩性的问题。

有人可以澄清我在这方面的理解吗?

最佳答案

我认为这可能是因为在查询之前扩展组而变得过于复杂。如何在文档索引中保留原样的组标识符呢?

通常,我用两个索引来表示(没有父子关系,或者根本没有任何嵌套关系)。

用户索引
(样本文档)

{
  "user_id": 12345,
  "user_name": "Swami PR"
  "user_group_ids": [900, 901, 902]
}

文档索引
(样本文档)
{
  "doc_id": 98765,
  "doc_name": "Lunch Order for Tuesday - Top Secret and Confidential",
  "doc_acl_read_users": [12345, 12346, 12347],
  "doc_acl_write_users": [12345],
  "doc_acl_read_groups": [435, 620],
  "doc_acl_write_groups": []
}

用户索引可以很容易地存在于数据库中...您的应用程序在查询文档时只需要可用的“Swami”的user_idgroup_ids

然后,当您将[Top Secret]文档查询为Swami PR时(要读取),请确保添加:
"should": [
  {
    "term": {
      "doc_acl_read_users": 12345
    }
  },
  {
    "terms": {
      "doc_acl_read_groups": [900, 901, 902]
    }
  },
  "minimum_should_match": 1
]

我可以看到两种主要的更新类型:
  • 文档上更新的用户或组:=重新索引文档索引中的一条记录
  • 用户已添加到组中或从组中删除:=重新索引用户索引中的一条记录

  • 带边盒
  • 用户或组已删除

  • 关于elasticsearch - ElasticSearch内容ACL过滤性能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34426183/

    10-13 07:52