【问题标题】:Search query Elasticsearch with Ngram returns 0 results always使用 Ngram 搜索查询 Elasticsearch 总是返回 0 个结果
【发布时间】:2019-02-27 17:00:26
【问题描述】:

我使用 NEST 来处理 Elasticsearch。我尝试将所有字符串字段分解为标记。同时对于 tokininiz 使用 ngram。但是,在提示查询时,我总是得到 0 个结果。

我的班级使用 api。

public class Elasticsearch
{
    string index = "video-materials";
    ElasticClient client;
    public Elasticsearch()
    {
        var settings = new ConnectionSettings(new Uri("http://localhost:9200"));
        client = new ElasticClient(settings);
        if (client.IndexExists(index).Exists)
        {
            client.DeleteIndex(index);
        }
        var nGramFilters = new List<string> { "lowercase", "asciifolding", "nGram_filter" };

        var resp = client.CreateIndex(index, c => c
             .Mappings(m => m
                .Map<ElasticVideoMaterial>(mm => mm
                    .AutoMap()
                    .Properties(p => p
                        .Text(t => t
                            .Name(n => n.OriginalTitle)
                            .Fields(f => f
                                .Keyword(k => k
                                    .Name("keyword")
                                    .IgnoreAbove(256)
                                )
                                .Text(tt => tt
                                    .Name("ngram")
                                    .Analyzer("ngram_analyzer")
                                )
                            )
                        )
                    )
                )
            )
            .Settings(s => s
                .Analysis(a => a
                    .Analyzers(anz => anz
                        .Custom("ngram_analyzer", cc => cc
                            .Filters(nGramFilters)
                            .Tokenizer("ngram_tokenizer")))
                    .Tokenizers(tz => tz
                        .NGram("ngram_tokenizer", td => td
                            .MinGram(3)
                            .MaxGram(3)
                            .TokenChars(TokenChar.Letter, TokenChar.Digit)
                        )
                    )
                )
            )
        );
    }
    public void Index(IEnumerable<ElasticVideoMaterial> models)
    {
        foreach(var model in models)
        {
            client.Index(model,i=>i.Index(index));
        }
    }
    public void Search(string query)
    {
        var resp = client.Search<ElasticVideoMaterial>(i => i
                                                        .Query(q => q
                                                            .Match(m => m
                                                                .Field(f => f.OriginalTitle.Suffix("ngram"))
                                                                .Query("Hob")
                                                            )
                                                        )
                                                        .Index(index)
                                                    ).Documents.ToList();
    }
}

我总是再次创建索引,然后为对象列表编制索引。 为此,请使用 Index() 方法。 这是我的索引类。

public class ElasticVideoMaterial
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string OriginalTitle { get; set; }
    public float? KinopoiskRating { get; set; }
    public float? Imdb { get; set; }
    public int Duration { get; set; }
    public List<string> GenreTitles { get; set; }
    public List<string> CountryNames { get; set; }
    public DateTime? ReleaseDate { get; set; }
    public List<string> TranslationTitles { get; set; }
    public List<string> FilmMakerNames { get; set; }
    public List<string> ActorNames { get; set; }
    public List<string> ThemeNames { get; set; }
    public CompletionField Suggest { get; set; }
}

但是当我尝试使用 Search() 方法获取结果时,我得到 0 个结果。 (写完《霍比特人》,希望能收到名字里有《霍比特人》的电影)

【问题讨论】:

    标签: .net elasticsearch nest


    【解决方案1】:

    ngram_analyzer 用于分析搜索请求的查询输入,但此分析器不用于分析索引请求的OriginalTitle 输入。

    您只需要在索引文档时配置用于OriginalTitle字段的分析器,可以使用attribute mapping或fluent mapping指定。比如流畅的映射

    var client = new ElasticClient();
    
    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);
    
    var nGramFilters = new List<string> { "lowercase", "asciifolding", "nGram_filter" };
    
    var resp = client.CreateIndex(defaultIndex, c => c
         .Mappings(m => m
            .Map<ElasticVideoMaterial>(mm => mm
                .AutoMap()
                .Properties(p => p
                    .Text(t => t
                        .Name(n => n.OriginalTitle)
                        .Fields(f => f
                            .Keyword(k => k
                                .Name("keyword")
                                .IgnoreAbove(256)
                            )
                            .Text(tt => tt
                                .Name("ngram")
                                .Analyzer("ngram_analyzer")
                            )
                        )
                    )
                )
            )
        )
        .Settings(s => s
            .Analysis(a => a
                .Analyzers(anz => anz
                    .Custom("ngram_analyzer", cc => cc
                        .Filters(nGramFilters)
                        .Tokenizer("ngram_tokenizer")))
                .Tokenizers(tz => tz
                    .NGram("ngram_tokenizer", td => td
                        .MinGram(3)
                        .MaxGram(3)
                        .TokenChars(TokenChar.Letter, TokenChar.Digit)
                    )
                )
            )
        )
    );
    
    var searchResponse = client.Search<ElasticVideoMaterial>(i => i
        .Query(q => q
            .Match(m => m
                .Field(f => f.OriginalTitle.Suffix("ngram"))
                .Query("Hob")
            )
        )
    );
    

    这会将OriginalTitle 设置为multi-field,并在OriginalTitle 下创建一个名为ngram 的多字段,该字段将在索引时和搜索时使用ngram_analyzer。

    【讨论】:

    • 感谢您的回复。但是,我按照您所做的一切都做了,结果仍然是 0。请告诉我,我有什么问题吗?
    • 应该在索引期间进行分析还是需要单独提出请求?
    • 可能是你分析的问题?您是否删除了现有索引并使用上述映射创建了新索引?您能否编辑您的问题以显示一个完整的示例,我们可以使用它来查找问题?
    猜你喜欢
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 2015-11-01
    相关资源
    最近更新 更多