ElasticSearch用于带空格的术语

时间:2013-01-15 08:33:08

标签: elasticsearch

我们正在运行ElasticSearch,并在搜索包含空格的术语时遇到一些问题。一个具体的例子:有一个名叫JM Bruno的人,但是在搜索时没有返回任何结果。我模糊地记得搜索这个确切的术语确实返回了结果,但我现在无法重现。

我尝试在我的tokenizer模式中添加空格和“\”,没有太多运气。 ES设置如下(在Ruby on Rails应用程序中使用Tire gem)

module Search
def self.included base
base.send :include, Tire::Model::Search
base.send :include, Tire::Model::Callbacks

base.class_eval do
  settings  analysis: {
              filter: {
                ngram: {
                  type: 'nGram',
                  max_gram: 12,
                  min_gram: 3
                },
                url_stop: {
                  type: "stop",
                  stopwords: %w[http https]
                }
              },
              tokenizer: {
                url_email_tokenizer: {
                  pattern: '[^\w\-\.@]+',
                  type: 'pattern'
                }
              },
              analyzer: {
                url_analyzer: {
                  tokenizer: "url_email_tokenizer",
                  filter: %w[url_stop ngram],
                  type: "custom"
                },
                name_analyzer: {
                  tokenizer: 'url_email_tokenizer',
                  filter: 'ngram',
                  type: 'custom'
                }
              }
            }


    end
  end
end

我们也使用这些标记符来搜索域名和电子邮件地址。

5 个答案:

答案 0 :(得分:4)

尝试使用您应用于现场的分析仪运行_analyze API

curl -XGET 'localhost:9200/_analyze?analyzer=name_analyzer' -d 'JM Bruno'

您将看到Elasticsearch如何将您的字段内容分解为令牌以及您无法使用TermQuery搜索它的原因。不对TermQuery进行分析,因此它会将您的查询与反向索引完全比较。

答案 1 :(得分:0)

您需要设置multi-field type

另请看一下这个非常酷的tutorial

答案 2 :(得分:0)

可以使用

来代替术语查询

在Java中,通过使用高级休息客户端

query.must((QueryBuilders.matchQuery("name", searchMap.get("JM Bruno")).minimumShouldMatch("100%")));

直接在弹性搜索中

GET / _search

{
    "query": {
        "match" : {
            "name" : {
                "query" : "JM Bruno",
                "cutoff_frequency" : 0.001
            }
        }
    }
}

答案 3 :(得分:0)

我正在使用Django,在那儿我通过将分析器设置为“关键字”遇到了此错误。而已。默认情况下,它使用“标准”分析器。

它不会基于空格生成令牌。它将把您的整个文本视为单个标记。默认限制是最多256个字符。

这是我的代码。我使用了elasticsearch_dsl。这是我的document.py文件

from django_elasticsearch_dsl import Document, fields
from elasticsearch_dsl import analyzer
from .models import Job

html_strip = analyzer(
    'html_strip',
    tokenizer= 'keyword',
    filter=['lowercase'],
)

@registry.register_document
class MyDocument(Document):
    title = fields.TextField(
        analyzer=html_strip,
        fields={'raw': fields.KeywordField()}
    )

class Index:
    name = 'jobs'  # Name of Elasticsearch index
    settings = {
        'number_of_shards': 1,
        'number_of_replicas': 0
    }

class Django:
    model = Job
    fields = [
        'salary_min',
        'salary_high'
    ]

这是我的view.py文件。在这里,我正在查询搜索对象。在这里,我正在使用一个传递关键字且需要搜索的函数。

def search_job_titles_for_autocomplete(keyword):
    autocomplete = list()
    search = f"*{keyword}*"

    queryset = JobDocument.search().query('wildcard', title=search)
    
    for job in queryset:
        job_to_dict = job.to_dict()
        autocomplete.append(job_to_dict["title"])

return autocomplete

它返回标题列表,我的问题已解决。

答案 4 :(得分:-1)

我遇到了同样的问题,我唯一想到的就是用“?”代替空格字符。通配符。它看起来像默认的标记化器以及我在查询字符串搜索中特别请求的那个被忽略了。