首页 > 解决方案 > Elastic search 2.0 搜索类似查询

问题描述

这是我的模型:

[ElasticsearchType(Name = "projectmodel")]
public class ProjectModel
{          
    public string name { get; set; }
    public string description { get; set; }
    [Nested]
    [JsonProperty("taskmodels")]
    public List<TaskModel> taskmodels { get; set; }
}

public class TaskModel
{       
    public string title { get; set; }
    public string description { get; set; }
}

我使用以下代码在主对象和嵌套对象中进行搜索。

        var searchResults = client.Search<ProjectModel>(
            body => body.Query(
                query => query.Bool(
                    bq => bq.Should(
                        q => q.Match(p => p.Field(f => f.name).Boost(6).Query(keyword)),                            
                        q => q.Match(p => p.Field(f => f.description).Boost(6).Query(keyword)),
                            sh => sh.Nested(n => n.Path(p => p.taskmodels).Query(nq => nq.Match(
                                m => m.Query(keyword).Field("taskmodels.description")

                                )
                            )
                            ),
                            sh => sh.Nested(n => n.Path(p => p.taskmodels).Query(nq => nq.Match(
                                m => m.Query(keyword).Field("taskmodels.title")

                                )
                            )
                            )
                        )

                    )
                ).Size(MAX_RESULT)
            );

这会毫无问题地搜索对象。但我需要为 searchText 输入确切的单词才能得到结果。

举个例子:名字——“科技”

如果我用技术搜索,它会返回记录。但是如果我用 techno 搜索,它没有返回记录。我该如何解决这个问题?

标签: c#searchelasticsearch-2.0

解决方案


您可以在您的字段上添加match_phrase_prefix查询。

Match_phrase_prefix 将在您的搜索查询中获取最后一个标记并对其进行短语前缀匹配。令牌的顺序很重要。如果要搜索文本中的任何位置,则需要创建n-grams和 edge_grams of tokens

var searchResults = _elasticClient.Search<ProjectModel>(
            body => body.Query(
                query => query.Bool(
                    bq => bq.Should(
                        q=> q.MatchPhrasePrefix(p=>p.Field(f=>f.name).Query(keyword)) --> note
                        q => q.Match(p => p.Field(f => f.name).Boost(6).Query(keyword)),
                        q => q.MatchPhrasePrefix(p => p.Field(f => f.description).Boost(6).Query(keyword)),
                            sh => sh.Nested(n => n.Path(p => p.taskmodels).Query(nq => nq.Match(
                                m => m.Query(keyword).Field("taskmodels.description")

                                )
                            )
                            ),
                            sh => sh.Nested(n => n.Path(p => p.taskmodels).Query(nq => nq.Match(
                                m => m.Query(keyword).Field("taskmodels.title")

                                )
                            )
                            )
                        )

                    )
                ).Size(MAX_RESULT)
            );

match、matchphrase 和 matchphraseprefix 之间的区别

假设有一个包含字段“description”的文档:“science and technology”,这个文本被分成单独的标记[“science”,“and”,“technology”],并以倒排索引排列。

如果要查找“科技”,可以使用匹配查询。由于单词的匹配顺序无关紧要,因此您在搜索“技术科学”时也会得到文档。它只匹配令牌。

如果订单对您很重要,则仅使用 match_phrase "science and technology" 将返回文档。

如果要搜索部分句子“科学和技术”,请使用 match_phrase_prefix 。前缀匹配仅在最后一个标记上执行,因此您无法搜索“scie and techno”。为此,还有其他选项,例如 edge-ngrams 和 ngrams


推荐阅读