在弹性搜索中支持动态列的查询

时间:2016-01-01 13:37:18

标签: search elasticsearch

我需要支持在弹性搜索中查询动态(非预定义)标签。假设我有一个博客文档,并希望支持对不同列集的查询,即tagTypeA = valueX& tagTypeB = ValueY,并且事先不知道这些tagTypeX列。每个标签只有一个值。用户将这个附加数据作为Map String :: String传递给我的API(没有严格的模型/结构)。我还需要支持这些标记列上的聚合查询。

我正在考虑支持此功能的三种方法。

  1. 声明我只能为每个文档支持最多N种动态标记(例如10)并创建内部列,如Tag1,Tag2 ... Tag10。现在有一个配置来维护TagTypeA = Tag1,TagTypeB = Tag2等的映射。在代码中,迭代输入键值对并使用key到columnName映射动态生成ES搜索查询。
  2. 优点:易于实施

    缺点:维护映射的开销。每次必须修改新类型的文档/客户端/必须为现有客户端添加新字段。

    1. 在ES中使用字符串数组创建一个未分析的字段。存储数据时,以密钥+"分隔符" +值的连续格式存储。因此,如果输入映射具有TagTypeA = Good& TagTypeB = High,然后将其存储为ES中的[" TagTypeA-Good"," TagTypeB-High"]。当用户查询时,构造回联系的字符串并搜索它们。
    2. 优点:板载新客户端/添加或更新新字段无需更改代码

      缺点:首先,它听起来并不干净。关键不应该有Delimeter。由于我们必须更改所有现有字符串值的值,因此在稍后的时间点更改映射非常繁琐。

      1. 不要定义任何架构,让json键 - 值标签对通过弹性搜索PUT调用。对于任何尚未存在的新密钥,弹性搜索会自动将其添加到具有默认类型推断的索引中(使用动态模板进行控制,并限制所有字段名称应以特定前缀开头)。
      2. 优点:没有配置或手动连接输入。处理中添加的任何列都是透明的,无需任何手动操作。

        缺点:我相信这会有一些缺点。但是不能想到任何具体的东西。请指教?我可以想到的一个问题是,由于字段名称被遗漏,任何一个滥用客户端都可能膨胀索引,这可能会因为大量字段而导致整个集群崩溃,除非我们有一个工作流程来手动注册&批准这些字段在单独的DB中。还有其他的缺点吗?

        我个人正在考虑与选项#3保持一致。

        任何人都可以就上述三种方法分享您的观点,如果有更好的方法可以解决这个问题。

        谢谢, 哈里什

1 个答案:

答案 0 :(得分:2)

我的胆量也告诉我,选项#3是最可行的选项。使用动态模板配置可能出现的新标签是一种很好的方法。

由于这些标签始终是名为TagTypeX的标签,因此很容易将该动态模板配置为始终存储not_analyzed值,因此没有理由说“这可能并不总是符合要求”,标签是一个标签,不应该有不同的搜索方式。如果是这种情况,则需要另一种字段类型。

就个人而言,我认为这种方法没有多大用处。它既灵活又具有进化性,并且不会仅仅基于纯粹的技术原因而混淆标签数据,如其他选项。

如果您有新标签,选项1显然会增加过多的开销,并且没有真正原因限制标签数量(从技术原因来看,从用户的角度来看,这不是一个正当理由)。

选项2将是一个维护的麻烦,正如你所说,它是不干净的。

可能还有其他选项,但这取决于您构建查询的方式(即查询DSL或只是URL中的查询字符串查询),所以我暂时不会在那里潜水。