Как реализовать предложение завершения с помощью NEST 6.1.0?

Пока у меня есть это (для индексации):

var createIndexResponse = await elasticClient.CreateIndexAsync(indexName, c => c
    .InitializeUsing(indexConfig)
    .Mappings(m => m
        .Map<ElasticsearchModel>(mm => mm
            .Properties(
            p => p
            .Completion(cp => cp
                .Name(elasticsearchModel => elasticsearchModel.StringTest)
                .Analyzer("simple")
                .SearchAnalyzer("simple")
            )
            .Text(t => t.Name(elasticsearchModel => elasticsearchModel.StringTest).Analyzer("customAnalyzerLowercaseSynonymAsciifolding"))
            )
        )
    )
);

Я добрался до этого с помощью этого сообщения (но я не уверен, что это правильно, поскольку я думаю, что мне не хватает некоторых свойств, чтобы установить минимальную длину предложения и т. д.): https://stackoverflow.com/a/33796953/7199922

Теперь я не могу понять, как запросить его, чтобы получить результаты предложения.

Я погуглил репозиторий git, например search suggest site:https://github.com/elastic/elasticsearch-net/, и проверил документацию, но ничего не нашел.


person Tadej    schedule 15.05.2018    source источник
comment
Взгляните на gist.github.com/russcam/68d891ad880d055dfb05e66b289f5926 Это для 5.x, но с небольшими изменениями (InferMappingFor<T> -> DefaultMappingFor<T>) то же самое и для 6.x   -  person Russ Cam    schedule 16.05.2018
comment
@RussCam, спасибо! Я получил его на работу сейчас. Я впервые реализовал функцию предложения, и ваша ссылка на github мне очень помогла. Если для вас не слишком много времени, напишите ответ на всякий случай, если ссылка больше не будет работать в будущем. Я могу сделать это, если у вас нет времени, просто дайте мне знать.   -  person Tadej    schedule 16.05.2018
comment
Рад, что ты разобрался. План состоит в том, чтобы задокументировать подсказки в документации NEST, когда будет момент :)   -  person Russ Cam    schedule 16.05.2018


Ответы (1)


Я закончил со следующим:

Модель

public class ElasticsearchModel
{
  public int IntTest { get; set; }
  public string StringTest { get; set; }
  public CompletionField StringTestSuggest
  {
      get
      {
          return new CompletionField
          {
              Input = new[] { StringTest + " ThisIsTheStringTestSuggestField" }
          };
      }
  }
}

Индексирование

var indexSettings = new IndexSettings
{
    NumberOfReplicas = 0, // If this is set to 1 or more, then the index becomes yellow.
    NumberOfShards = 5 
};

var indexConfig = new IndexState
{
    Settings = indexSettings
};

var createIndexResponse = elasticClient.CreateIndex(indexName, c => c
   .InitializeUsing(indexConfig)
   .Mappings(m => m
       .Map<ElasticsearchModel>(mm => mm
           .Properties(
           p => p
           .Completion(cp => cp
               .Name(elasticsearchModel => elasticsearchModel.StringTestSuggest)
               .Analyzer("customAnalyzerLowercaseSynonymAsciifolding")
               .SearchAnalyzer("customAnalyzerLowercaseSynonymAsciifolding")
           )
           .Text(t => t.Name(product => product.IntTest).Analyzer("keyword"))
           .Text(t => t.Name(elasticsearchModel => elasticsearchModel.StringTest).Analyzer("customAnalyzerLowercaseSynonymAsciifolding")) // You can use "standard" here or some other default analyzer.               
           )
       )
   )
);

elasticClient.Refresh(indexName);

Запрос

public List<ElasticsearchModel> Suggest(string indexName, string query)
{
    var elasticClient = ElasticsearchHelper.DatabaseConnection();

    var response = elasticClient.Search<ElasticsearchModel>(s => s
       .Index(indexName)
        .Suggest(su => su
            .Completion("StringTest", cs => cs
                .Field(f => f.StringTestSuggest)
                .Prefix(query)
                .Fuzzy(f => f
                    .Fuzziness(Fuzziness.Auto)
                )
                .Size(5)
            )
        )
     );

    var suggestions =
        from suggest in response.Suggest["StringTest"]
        from option in suggest.Options
        select new ElasticsearchModel
        {
            IntTest = option.Source.IntTest,
            StringTest = option.Source.StringTest
        };

    return suggestions.ToList();
}

Другое (чтобы легче понять методы)

public void Refresh(string indexName)
{
    var elasticClient = ElasticsearchHelper.DatabaseConnection();
    elasticClient.Refresh(indexName); // This should be called before every query or everytime documents get indexed! Else some results might be missing.
}

Инициировать подключение к базе данных ES

public static class ElasticsearchHelper
{
    public static ElasticClient DatabaseConnection()
    {
        var node = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
        //var node = new Uri("http://localhost:9200");
        var settings = new ConnectionSettings(node)
            .PrettyJson()
            .DisableDirectStreaming() // Enable for API HTTP request/response debugging.
            .OnRequestCompleted(callDetails =>
            {
                // log out the request
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("REQUEST:");
                Console.ResetColor();

                if (callDetails.RequestBodyInBytes != null)
                {
                    Console.WriteLine(
                        $"{callDetails.HttpMethod} {callDetails.Uri} \n" +
                        $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");
                }
                else
                {
                    Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
                }

                // log out the response
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("RESPONSE:");
                Console.ResetColor();

                if (callDetails.ResponseBodyInBytes != null)
                {
                    Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                             $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                             $"{new string('-', 30)}\n");
                }
                else
                {
                    Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                             $"{new string('-', 30)}\n");
                }
            }) // For debugging...
        ; // Index name must be lowercase, cannot begin with an underscore, and cannot contain commas.
        var client = new ElasticClient(settings);

        return client;
    }






}

Все кредиты и спасибо за помощь Russ Cam.

person Tadej    schedule 16.05.2018
comment
Комментарий // This should be called before every query or everytime documents get indexed! Else some results might be missing., как правило, не является хорошим советом для производственных систем, поскольку он приводит к записи новых сегментов и, вероятно, снижает производительность. Гораздо лучше установить разумный интервал обновления для производства. Обновление для тестов — хорошая идея :) Взгляните на elastic.co/guide/en/elasticsearch/guide/current/ - person Russ Cam; 17.05.2018
comment
@RussCam спасибо за заметку. Это некоторые комментарии в моем тестовом проекте, которые я забыл удалить перед публикацией здесь. :) - person Tadej; 17.05.2018