gpt4 book ai didi

elasticsearch - Spring数据ElasticSearch通配符搜索

转载 作者:行者123 更新时间:2023-11-29 02:56:02 27 4
gpt4 key购买 nike

我正在尝试在以下文本列表中搜索单词 blue

“BlueSaphire”,“Bluo”,“alue”,“blue”,“BLUE”,
“蓝”,“蓝黑”,“蓝”,“蓝 gem 蓝”,
“黑色”,“绿色”,“bloo”,“Saphireblue”

SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color")
.withQuery(matchQuery("colorDescriptionCode", "blue")
.fuzziness(Fuzziness.ONE)
)
.build();

效果很好,搜索结果将返回以下记录以及得分
alue    2.8718023
Bluo 1.7804208
Bluo 1.7804208
BLUE 1.2270637
blue 1.2270637
Blue 1.2270637
Blue Black 1.1082436
Saphire Blue 0.7669148

但是我无法使通配符起作用。 “SaphireBlue”和“BlueSaphire”也有望成为结果的一部分

我尝试了以下设置,但不起作用。
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color")
.withQuery(matchQuery("colorDescriptionCode", "(.*?)blue")
.fuzziness(Fuzziness.ONE)
)
.build();

在堆栈溢出中,我观察到一种指定分析通配符的解决方案。
QueryBuilder queryBuilder = boolQuery().should(
queryString("blue").analyzeWildcard(true)
.field("colorDescriptionCode", 2.0f);

我找不到queryString静态方法。我正在使用spring-data-elasticsearch 2.0.0.RELEASE。

让我知道如何指定通配符,以便包含 blue 的所有单词也将在搜索结果中返回

最佳答案

我知道工作示例总是比理论更好,但是我还是要先讲一点理论。 Elasticsearch的核心是Lucene。因此,在将文档写入Lucene索引之前,他要经过分析阶段。分析阶段可分为3部分:

  • 字符过滤;
  • 标记化;
  • token 过滤

  • 在第一阶段,我们可以丢弃不需要的字符,例如HTML标签。有关字符过滤器的更多信息,可以在 official site上找到。
    下一阶段要有趣得多。在这里,我们将输入文本拆分为标记,这些标记将在以后用于搜索。一些非常有用的 tokenizers:
  • 标准 token 生成器。默认情况下使用。分词器实现Unicode文本分段算法。在实践中,您可以使用此选项将文本拆分为多个单词,并将这些单词用作标记。
  • n-gram分词器。如果您想按单词的一部分进行搜索,这就是您所需要的。该标记器将文本拆分为n个项目的连续序列。例如,文本“例如”将被拆分为 token "fo", "or", "r ", " e", "ex", "for", "or ex"等 token 的此序列。n-gram的长度是可变的,可以通过min_gram和max_gram参数进行配置。
  • 边缘n-gram标记器。除了一件事外,其工作方式与n-gram标记器相同-该标记器不增加偏移量。例如,文本“例如”将被拆分为 token "fo", "for", "for ", "for e", "for ex", "for exa"等 token 的此序列。
    您可以在官方网站上找到有关分词器的更多信息。不幸的是,由于声誉低下,我无法发布更多链接。

  • 下一阶段也很有趣。将文本拆分为标记后,我们可以执行很多有趣的操作。我再次给出一些非常有用的 token 过滤器示例:
  • 小写过滤器。在大多数情况下,我们希望获得不区分大小写的搜索,因此,最好将标记改为小写。
  • 词干过滤器。当我们处理自然语言时,就会遇到很多问题。问题之一是一个词可以有多种形式。词干过滤器可帮助我们获得单词的词根形式。
  • 模糊度过滤器。另一个问题是用户经常打错字。此过滤器添加包含可能的错字的标记。

  • 如果您有兴趣查看分析器的结果,则可以使用此_termvectors端点
    curl [ELASTIC_URL]:9200/[INDEX_NAME]/[TYPE_NAME]/[DOCUMENT_ID]/_termvectors?pretty

    现在谈论查询。查询分为两个大组。这些组有2个重大差异:
  • 请求是否将经过分析阶段;
  • 请求是否要求确切答案(是或否)

  • 示例包括匹配查询和术语查询。第一个将通过分析阶段,第二个则不会。第一个不会给我们一个具体的答案(但是给我们一个分数),第二个会给我们答案。为文档创建映射时,我们可以在每个字段中分别指定分析器的索引和搜索分析器的索引。

    现在有关 Spring 数据elasticsearch的信息。在这里谈论具体示例是有意义的。假设我们有一个带有标题字段的文档,并且想要搜索有关此字段的信息。首先,创建一个带有用于Elasticsearch设置的文件。
    {
    "analysis": {
    "analyzer": {
    "ngram_analyzer": {
    "tokenizer": "ngram_tokenizer",
    "filter": [
    "lowercase"
    ]
    },
    "edge_ngram_analyzer": {
    "tokenizer": "edge_ngram_tokenizer",
    "filter": [
    "lowercase"
    ]
    },
    "english_analyzer": {
    "tokenizer": "standard",
    "filter": [
    "lowercase",
    "english_stop",
    "unique",
    "english_possessive_stemmer",
    "english_stemmer"
    ]
    "keyword_analyzer": {
    "tokenizer": "keyword",
    "filter": ["lowercase"]
    }

    },
    "tokenizer": {
    "ngram_tokenizer": {
    "type": "ngram",
    "min_gram": 2,
    "max_gram": 20
    },
    "edge_ngram_tokenizer": {
    "type": "edge_ngram",
    "min_gram": 2,
    "max_gram": 20
    }
    },
    "filter": {
    "english_stop": {
    "type": "stop",
    "stopwords": "_english_"
    },
    "english_stemmer": {
    "type": "stemmer",
    "language": "english"
    },
    "english_possessive_stemmer": {
    "type": "stemmer",
    "language": "possessive_english"
    }
    }
    }

    您可以将此设置保存到资源文件夹。现在让我们看一下我们的文档类
    @Document(indexName = "document", type = "document")
    @Setting(settingPath = "document_index_setting.json")
    public class Document {

    @Id
    private String id;

    @MultiField(
    mainField = @Field(type = FieldType.String,
    index = not_analyzed),
    otherFields = {
    @InnerField(suffix = "edge_ngram",
    type = FieldType.String,
    indexAnalyzer = "edge_ngram_analyzer",
    searchAnalyzer = "keyword_analyzer"),
    @InnerField(suffix = "ngram",
    type = FieldType.String,
    indexAnalyzer = "ngram_analyzer"),
    searchAnalyzer = "keyword_analyzer"),
    @InnerField(suffix = "english",
    type = FieldType.String,
    indexAnalyzer = "english_analyzer")
    }
    )
    private String title;

    // getters and setters omitted

    }

    因此,这里的字段标题包含三个内部字段:
  • title.edge_ngram用于使用关键字搜索分析器按边缘n元语法进行搜索。我们需要这样做是因为我们不需要将查询拆分为边缘n元语法;
  • title.ngram用于按n-gram进行搜索;
  • title.english用于使用自然语言的细微差别进行搜索
    和主场标题。我们不对此进行分析,因为有时我们希望按此字段进行排序。
    让我们使用简单的多匹配查询来搜索所有这些字段:

  • String searchQuery = "blablabla";
    MultiMatchQueryBuilder queryBuilder = multiMatchQuery(searchQuery)
    .field("title.edge_ngram", 2)
    .field("title.ngram")
    .field("title.english");
    NativeSearchQueryBuilder searchBuilder = new NativeSearchQueryBuilder()
    .withIndices("document")
    .withTypes("document")
    .withQuery(queryBuilder)
    .withPageable(new PageRequest(page, pageSize));
    elasticsearchTemplate.queryForPage(searchBuilder.build,
    Document.class,
    new SearchResultMapper() {
    //realisation omitted });


    搜索是一个非常有趣且庞大的话题。我试图尽可能简短地回答,有可能因为这个原因而出现混乱的时刻-不要犹豫了。

    关于elasticsearch - Spring数据ElasticSearch通配符搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45587293/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com