Поисковый запрос Elasticsearch с Ngram всегда возвращает 0 результатов - PullRequest
0 голосов
/ 27 февраля 2019

Я использую NEST для работы с Elasticsearch.Я пытаюсь разбить все строковые поля на токены.В то же время для токининиза используйте 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 результатов.(Написав «Hob», я ожидаю получить фильмы, названия которых содержат «Hobbit»)

1 Ответ

0 голосов
/ 28 февраля 2019

ngram_analyzer используется для анализа ввода запроса поискового запроса, но этот анализатор не используется для анализа ввода OriginalTitle запроса индекса.

Вам просто нужно настроить анализатор, который будет использоваться для поля OriginalTitle при индексации документа, которое можно указать с помощью сопоставления атрибута или плавного сопоставления .Например, свободное отображение

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 в качестве мультиполя и создает мультиполе с именем ngram в OriginalTitle, в котором будет использоваться ngram_analyzer как во время индекса, так и во время поиска для этого поля.

...