Elasticsearch-使用NEST自动完成 [英] Elasticsearch - Autocomplete with NEST

查看:79
本文介绍了Elasticsearch-使用NEST自动完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用NEST客户端进行自动填充.

I'm trying to do autocomplete with the NEST client.

代码如下:

Poco(浓缩):

public class Course
{
    [ElasticProperty(Name="id")]
    public int ID { get; set; }
    public string Name { get; set; }   
    [ElasticProperty(Type = FieldType.Completion)]
    public CompletionField Suggest { get; set; }

    public Course(sm.Models.Course c)
    {
        if (c != null)
        {
            this.ID = c.ID;
            this.Name = c.Name;
            this.Suggest = new CompletionField
            {
                Input = new List<string>(this.Name.Split(' ')) { this.Name },
                Output = this.Name,
                Payload = new
                {
                    id = this.Name
                },
                Weight = 1
            };
        }
    }
}   

索引:

Client.CreateIndex("myindex", c => c
            .NumberOfReplicas(1)
            .NumberOfShards(5)
            .Settings(s => s
                .Add("merge.policy.merge_factor", "10")
                .Add("search.slowlog.threshold.fetch.warn", "1s")
            )
            .AddMapping<Course>(m => m.MapFromAttributes()
                .Properties(props => props
                    .Completion(s=>s
                        .Name(p=>p.Suggest)
                        .IndexAnalyzer("simple")
                        .SearchAnalyzer("simple")
                        .MaxInputLength(20)
                        .Payloads()
                        .PreservePositionIncrements()
                        .PreserveSeparators()
                    )
                )                
            ));

我的建议查询:

GET _suggest
{
  "course-suggest": {
   "text": "Nothilfe",
   "completion": {
     "field": "suggest",
     "size": 10
   }
  }
}

哪个会导致此错误:

    "failures": [
         {
            "shard": 1,
            "index": "myindex",
            "status": "INTERNAL_SERVER_ERROR",
            "reason": {
               "type": "exception",
               "reason": "failed to execute suggest",
               "caused_by": {
                  "type": "exception",
                  "reason": "Field [suggest] is not a completion suggest field"
               }
            }
         }

为什么我的建议字段不被识别为完成字段?

Why is my suggest field not recognized as a completion field?

获取_mapping/课程

GET _mapping/course

"suggest": {
  "properties": {
     "input": {
        "type": "string"
     },
     "output": {
        "type": "string"
     },
     "payload": {
        "properties": {
           "id": {
              "type": "string"
           }
        }
     },
     "weight": {
        "type": "long"
     }
  }

推荐答案

有几个可能的原因导致您收到此错误,但是最明显的原因是您在索引myindex中对类型course的映射.与您要发送的查询有关的过时.

There are a few possible reasons why you might be receiving this error, but the most obvious one is that your mapping for type course in index myindex is out of date in relation to the query you're sending through.

您可以轻松地通过以下方式检查类型的映射

You can easily check the the mapping for the type with

curl -XGET "http://localhost:9200/myindex/course/_mapping"

应该看起来像

{
   "myindex": {
      "mappings": {
         "course": {
            "properties": {
               "id": {
                  "type": "integer"
               },
               "name": {
                  "type": "string"
               },
               "suggest": {
                  "type": "completion",
                  "analyzer": "simple",
                  "payloads": true,
                  "preserve_separators": true,
                  "preserve_position_increments": true,
                  "max_input_length": 20
               }
            }
         }
      }
   }
}

如果没有,则需要通过以下方法解决此问题:删除索引中的类型并重新创建(或完全删除索引并重新创建),或者通过使用正确的映射创建新索引并复制文档如果要 * try * 保留所有已有数据,则可以从旧索引中删除(此处可能会或可能不会).

If it doesn't you'll need to fix this, either by deleting the type in the index and recreating (or deleting the index altogether and recreating), or by creating a new index with the correct mapping and copying documents over from the old index if you want to *try* to keep any data you already have (this may or may not be possible here).

以下内容将按预期创建索引并执行您要运行的suggest查询.请注意,我已将查询范围限定为仅针对索引myindex运行.类型

The following will create the index as expected and perform the suggest query you're trying to run. Note that I have scoped the query to run only against the index myindex. The types

public class Course
{
    [ElasticProperty(Name = "id")]
    public int ID { get; set; }

    public string Name { get; set; }

    [ElasticProperty(Type = FieldType.Completion)]
    public CompletionField Suggest { get; set; }

    public Course(Course c)
    {
        if (c != null)
        {
            this.ID = c.ID;
            this.Name = c.Name;
            this.Suggest = new CompletionField
            {
                Input = new List<string>(this.Name.Split(' ')) { this.Name },
                Output = this.Name,
                Payload = new
                {
                    id = this.Name
                },
                Weight = 1
            };
        }
    }
}

// I'm guessing CompletionField looks something like this?
public class CompletionField
{
    public List<string> Input { get; set; }
    public string Output { get; set; }
    public object Payload { get; set; }
    public double Weight { get; set; }
}

以及创建索引和查询

void Main()
{
    var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
        .ExposeRawResponse(true)
        .SetConnectionStatusHandler(response =>
        {
            // log out the requests
            if (response.Request != null)
            {
                Console.WriteLine("{0} {1} \n{2}\n", response.RequestMethod.ToUpperInvariant(), response.RequestUrl,
                    Encoding.UTF8.GetString(response.Request));
            }
            else
            {
                Console.WriteLine("{0} {1}\n", response.RequestMethod.ToUpperInvariant(), response.RequestUrl);
            }

            if (response.ResponseRaw != null)
            {
                Console.WriteLine("{0}\n{1}\n\n{2}\n", response.HttpStatusCode, Encoding.UTF8.GetString(response.ResponseRaw), new String('-', 30));
            }
            else
            {
                Console.WriteLine("{0}\n\n{1}\n", response.HttpStatusCode, new String('-', 30));
            }
        });

    var client = new ElasticClient(settings);

    var indexResponse = client.CreateIndex("myindex", c => c
        .NumberOfReplicas(1)
        .NumberOfShards(5)
        .Settings(s => s
            .Add("merge.policy.merge_factor", "10")
            .Add("search.slowlog.threshold.fetch.warn", "1s")
        )
        .AddMapping<Course>(m => m.MapFromAttributes()
                .Properties(props => props
                    .Completion(s => s
                        .Name(p => p.Suggest)
                        .IndexAnalyzer("simple")
                        .SearchAnalyzer("simple")
                        .MaxInputLength(20)
                        .Payloads()
                        .PreservePositionIncrements()
                        .PreserveSeparators()
                    )
                )
        ));

    // give Elasticsearch some time to initialize the index
    Thread.Sleep(TimeSpan.FromSeconds(5));

    var suggestResponse = client.Suggest<Course>(s => s
        .Index("myindex")
        .Completion("course-suggest", c => c
            .Text("Nothilfe")
            .OnField("suggest")
            .Size(10)
        )
    );

    // do something with suggestResponse
}

这会将以下内容注销到控制台

This logs out the following to the console

POST http://localhost:9200/myindex 
{
  "settings": {
    "index": {
      "number_of_replicas": 1,
      "number_of_shards": 5,
      "merge.policy.merge_factor": "10",
      "search.slowlog.threshold.fetch.warn": "1s"
    }
  },
  "mappings": {
    "course": {
      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "suggest": {
          "type": "completion",
          "search_analyzer": "simple",
          "index_analyzer": "simple",
          "payloads": true,
          "preserve_separators": true,
          "preserve_position_increments": true,
          "max_input_len": 20
        }
      }
    }
  }
}

200
{"acknowledged":true}

------------------------------

POST http://localhost:9200/myindex/_suggest 
{
  "course-suggest": {
    "text": "Nothilfe",
    "completion": {
      "field": "suggest",
      "size": 10
    }
  }
}

200
{"_shards":{"total":5,"successful":5,"failed":0}}

------------------------------

这篇关于Elasticsearch-使用NEST自动完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆