当前位置: 首页 > 知识库问答 >
问题:

Elasticsearch 5.2.2:术语聚合不区分大小写

邓星光
2023-03-14

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

到目前为止,我尝试的是添加一个名为“小写”的自定义分析器,它使用“关键字”标记器和“小写”过滤器。然后,我在映射中添加了一个名为“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"
            }
          }
        }
      }
    }
  }
}

现在,我添加了两条记录,其作者相同,但案例不同:

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
}

因此,在我看来,聚合认为搜索字段是文本而不是关键字,因此给了我fielddata警告。我认为ES足够复杂,可以识别术语字段实际上是一个关键字(通过自定义分析器),因此可以聚合,但事实并非如此。

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

做这种类型的不敏感关键字聚合有最佳实践吗?我希望我可以在映射部分说"type":"keyword","filter":"小写",但这似乎不可用。

如果我走“fielddata”:true,感觉我不得不使用太大的棍子才能让它工作。在此方面的任何帮助都将不胜感激!

共有3个答案

洪子晋
2023-03-14

您确实将use_小写定义为文本:

“use_lowercase”:{“type”:“text”,“analyzer”:“lowercase”}

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

吕越彬
2023-03-14
匿名用户

在默认情况下,这似乎是不可能的(没有“小写”规范化器),但没有它,您可以使用技巧-在不区分大小写的正则表达式匹配中翻译字符串。

e、 g.对于字符串“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)

皇甫雨石
2023-03-14

事实证明,解决方案是使用自定义规范化器,而不是自定义分析器。

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
            }
          }
        }
      }
    }
  }
}

然后,这允许使用fieldAuthor聚合术语。使用小写字母。

 类似资料:
  • 我试图在elasticsearch中对术语聚合的桶进行排序,不区分大小写。以下是字段映射: 请注意,此处的此数据结构适用于PHP。 聚合如下所示: 这是可行的,但生成的桶是按字典顺序排列的。 我在这里找到了一些有趣的文档,它们解释了如何做到这一点,但这是在对点击进行排序的上下文中,而不是在聚合桶中。 我还是试过了。以下是我创建的分析器: 这里是更新的字段映射,使用分析器有一个名为“sort”的新子

  • 问题内容: 我正在尝试使用以下查询对以下数据进行elasticsearch来执行术语聚合,输出将名称分解为标记(请参见下面的输出)。因此,我尝试将os_name映射为multi_field,但现在无法通过它查询。是否可以有没有令牌的索引?例如“ Fedora Core”? 查询: 数据: 输出: 映射: 问题答案: 实际上,您应该像这样更改映射 并且您的aggs应该更改为:

  • 我有一个存储字符串数组的字段。不同的文档包含不同的字符串集。 现在,我使用这个聚合查询来分析每个文件类型的使用情况。 结果与预期一致。但最近我在删除XML文件支持后更新了此字段。因此,文档的non具有文件类型XML。我可以从这个查询中确认这一点。 总命中计数为零。奇怪的是,当我再次执行上述聚合查询时,我仍然可以将XML视为一个术语。doc count为零。 如果这个XML术语在任何文档中都不存在,

  • 我想知道如何在Elasticsearch中使用聚合时获得具有最高doc_count的存储桶。我正在使用Kibana示例数据kibana_sample_data_flights: 如果有一个存储桶具有最大文档计数,我可以将术语聚合的大小设置为1,但是如果有两个存储桶具有相同的最大文档计数,则这不起作用。 自从我涉足管道聚合以来,我觉得应该有一种简单的方法来实现这一点。最大桶聚合似乎能够处理多个最大桶

  • 我们目前正在开发一个多语言文档CMS。因此,我们有翻译成不同语言的文件。 对于使用Elasticsearch进行搜索,我们目前使用每种语言(德语、英语、法语……)一个索引,其中同一文档的所有翻译共享相同的ID。 当用户搜索特定术语时,我们希望在所有语言中搜索,但只返回不同ID的列表。据我所知,只有使用以下术语聚合才能做到这一点: 这很好,但是作为弹性搜索文档https://www.elastic.