【问题标题】:Elasticsearch autocomplete on large text field大型文本字段上的 Elasticsearch 自动完成
【发布时间】:2022-02-07 14:13:05
【问题描述】:

我使用的是 ES 7.x 版本,基本上要求是在具有文件/文档内容的大文本字段上提供自动建议/提前输入。

我已经探索了多种方法,如果我限制使用 _source,它会返回整个源文档或特定字段。我已经尝试过边缘 ngram 或 n-gram 标记器、前缀查询、完成建议器。

以下是示例文档(内容字段可能有 1000 多个句子):

{
    "content":"Elasticsearch is a distributed, free and open search and analytics engine for all types of data, including textual, numerical, geospatial, structured, and unstructured. 
Elasticsearch is built on Apache Lucene and was first released in 2010 by Elasticsearch N.V. (now known as Elastic). 
Known for its simple REST APIs, distributed nature, speed, and scalability, Elasticsearch is the central component of the Elastic Stack, a set of free and open tools for data ingestion, enrichment, storage, analysis, and visualization. Commonly referred to as the ELK Stack (after Elasticsearch, Logstash, and Kibana), 
the Elastic Stack now includes a rich collection of lightweight shipping agents known as Beats for sending data to Elasticsearch."
}

以下是预期输出:

搜索查询: el

输出:["elasticsearch","elastic","elk"]

搜索查询:分析电子

输出:[“分析引擎”]

目前我无法使用 OOTB 功能实现上述输出。因此,我使用了弹性搜索的突出显示功能并在结果上应用了正则表达式,并使用 Java 创建了唯一的建议列表。

下面是我目前使用高亮功能的实现。

索引映射:

PUT index
{
  "settings": {
    "index": {
      "number_of_shards": 2,
      "number_of_replicas": 1
    },
    "analysis": {
      "filter": {
        "stop_filter": {
          "type": "stop",
          "stopwords": "_english_"
        },
        "ngram_filter": {
          "token_chars": [
            "letter",
            "digit",
            "symbol",
            "punctuation"
          ],
          "min_gram": "1",
          "type": "edge_ngram",
          "max_gram": "12"
        }
      },
      "analyzer": {
        "text_english": {
          "type": "custom",
          "tokenizer": "uax_url_email",
          "filter": [
            "lowercase",
            "stop_filter"
          ]
        },
        "whitespace_analyzer": {
          "filter": [
            "lowercase"
          ],
          "type": "custom",
          "tokenizer": "whitespace"
        },
        "ngram_analyzer": {
          "filter": [
            "lowercase",
            "stop_filter",
            "ngram_filter"
          ],
          "type": "custom",
          "tokenizer": "letter"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "fields": {
          "autocorrect": {
            "type": "text",
            "analyzer": "ngram_analyzer",
            "search_analyzer": "whitespace_analyzer"
          }
        },
        "analyzer": "text_english"
      }
    }
  }
}

下面是从 Java 执行的 Elasticsearch 查询

POST autosuggest/_search
{
  "_source": "content.autocorrect",
  "query": {
    "match_phrase": {
      "content.autocorrect": "analytics e"
    }
  },
  "highlight": {
    "fields": {
      "content.autocorrect": {
        "fragment_size": 500,
        "number_of_fragments": 1
      }
    }
  }
}

我们在上面的查询结果中应用了正则表达式模式。

如果没有上述解决方法,请告诉我是否有任何方法可以实现。

【问题讨论】:

  • 完成建议器不是适合您的用例的工具。您是否尝试过 match_phrase_prefix 查询,该查询将完整的令牌一个一个地匹配,最后一个作为前缀?

标签: elasticsearch elastic-stack


【解决方案1】:

完成建议器不是适合您的用例的工具。同样,根据您拥有的内容量,ngram 和边缘 ngram 可能会过大。

您是否尝试过match_phrase_prefix query,它将完整的标记一个一个地匹配,最后一个作为前缀?

下面的查询非常简单,应该可以按您预期的方式工作。

POST test/_search
{
  "query": {
    "match_phrase_prefix": {
      "content": "analytics e"
    }
  }
}

【讨论】:

  • 这会像我预期的那样返回输出吗?就像您编写的查询一样,它不会返回整个内容字段并给出“分析引擎”作为建议?
  • 您仍然需要高亮部分,当然,我只是专注于查询,以确保它与您想要的完全匹配。但是您并不真的需要 ngram 分析器和所有这些东西恕我直言,您可以按原样匹配内容字段
  • 知道了。有什么可以使用聚合来实现的吗?
  • 这不是聚合问题,而是搜索问题。具有较小片段大小的荧光笔应该可以满足您的需要
  • 确实,因为没有匹配的第二个词的前缀...在这种情况下,也许您可​​以简单地使用 edge-ngram tokenizer(最小 2 / 最大 20)标记您的内容,它将索引所有您的内容的前缀,然后对输入值进行简单的match 查询就可以完成这项工作
猜你喜欢
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 2012-05-24
相关资源
最近更新 更多