【问题标题】:Elasticsearch 5.2.2: terms aggregation case insensitiveElasticsearch 5.2.2:术语聚合不区分大小写
【发布时间】:2017-07-19 21:51:53
【问题描述】:

我正在尝试对关键字类型字段进行不区分大小写的聚合,但在使其正常工作时遇到了问题。

到目前为止,我尝试添加一个名为“lowercase”的自定义分析器,它使用“keyword”标记器和“lowercase”过滤器。然后,我为要使用的字段向映射中添加了一个名为“use_lowercase”的字段。我还想保留现有的“文本”和“关键字”字段组件,因为我可能想在字段中搜索术语。

这是索引定义,包括自定义分析器:

PUT authors
{
  "settings": {
    "analysis": {
      "analyzer": {
        "lowercase": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": "lowercase"
        }
      }
    }
  },
  "mappings": {
    "famousbooks": {
      "properties": {
        "Author": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            },
            "use_lowercase": {
              "type": "text",
              "analyzer": "lowercase"
            }
          }
        }
      }
    }
  }
}

现在我添加了 2 条具有相同作者但大小写不同的记录:

POST authors/famousbooks/1
{
  "Book": "The Mysterious Affair at Styles",
  "Year": 1920,
  "Price": 5.92,
  "Genre": "Crime Novel",
  "Author": "Agatha Christie"
}

POST authors/famousbooks/2
{
  "Book": "And Then There Were None",
  "Year": 1939,
  "Price": 6.99,
  "Genre": "Mystery Novel",
  "Author": "Agatha christie"
}

到目前为止一切顺利。现在,如果我根据作者进行术语聚合,

GET authors/famousbooks/_search
{
  "size": 0,
  "aggs": {
    "authors-aggs": {
      "terms": {
        "field": "Author.use_lowercase"
      }
    }
  }
}

我得到以下结果:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [Author.use_lowercase] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory."
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "authors",
        "node": "yxcoq_eKRL2r6JGDkshjxg",
        "reason": {
          "type": "illegal_argument_exception",
          "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [Author.use_lowercase] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory."
        }
      }
    ],
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [Author.use_lowercase] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory."
    }
  },
  "status": 400
}

所以在我看来,聚合认为搜索字段是 text 而不是 keyword,因此给了我 fielddata 警告。我认为 ES 会足够复杂,可以识别 terms 字段实际上是一个关键字(通过自定义分析器),因此可以聚合,但情况似乎并非如此。

如果我将 "fielddata":true 添加到 Author 的映射中,那么聚合就可以正常工作,但考虑到设置此值时堆使用率过高的可怕警告,我犹豫是否这样做。

是否有进行这种不敏感关键字聚合的最佳实践?我希望我可以在 ma​​ppings 部分中说"type":"keyword", "filter":"lowercase",但这似乎不可用。

如果我走"fielddata":true 路线,感觉就像我不得不使用太大的棍子才能让它工作。对此的任何帮助将不胜感激!

【问题讨论】:

    标签: elasticsearch aggregation case-insensitive


    【解决方案1】:

    结果证明解决方案是使用自定义规范器而不是自定义分析器。

    PUT authors
    {
      "settings": {
        "analysis": {
          "normalizer": {
            "myLowercase": {
              "type": "custom",
              "filter": [ "lowercase" ]
            }
          }
        }
      },
      "mappings": {
        "famousbooks": {
          "properties": {
            "Author": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                },
                "use_lowercase": {
                  "type": "keyword",
                  "normalizer": "myLowercase",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      }
    }
    

    这样就可以毫无问题地使用字段Author.use_lowercase 进行术语聚合。

    【讨论】:

      【解决方案2】:

      您确实将 use_lowercase 定义为文本:

      "use_lowercase": { "type": "text", "analyzer": "lowercase" }

      尝试将其定义为 type: keyword - 它帮助我解决了与排序类似的问题。

      【讨论】:

      • 不幸的是,如果您还指定了分析器,则指定 type: keyword 而不是 type:text 会失败(因为我在这里做的是让小写部分工作)。设置映射时出现错误消息:[字段] 的映射定义具有不受支持的参数:[分析器:小写]
      【解决方案3】:

      这似乎在默认情况下是不可能的,(没有"lowercase" normalizer)但是没有这个你可以使用一个技巧——在不区分大小写的正则表达式匹配中翻译字符串。

      例如对于字符串"bar" - 不区分大小写的正则表达式为"[bB][aA][rR]"

      我使用了一个 python 助手来做这个:

      def case_insensitive_regex_from_string(v):
          if not v:
              return v
          zip_obj = zip(itertools.cycle('['), v, v.swapcase(), itertools.cycle(']'))
          return ''.join(''.join(x) for x in zip_obj)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-20
        • 2014-07-09
        • 1970-01-01
        • 2020-10-30
        • 2021-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多