簡體   English   中英

Elasticsearch - 使用NEST自動完成

[英]Elasticsearch - Autocomplete with NEST

我正在嘗試使用NEST客戶端進行自動完成。

代碼如下:

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"
               }
            }
         }

為什么我的建議字段未被識別為完成字段?

GET _mapping / course

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

您可能會收到此錯誤的原因有幾個,但最明顯的原因是索引myindex類型course的映射與您發送的查詢相關。

您可以輕松檢查類型的映射

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
               }
            }
         }
      }
   }
}

如果不是這樣,您需要通過刪除索引中的類型並重新創建(或完全刪除索引並重新創建),或者通過創建具有正確映射的新索引並從舊文件復制文檔來解決此問題。索引,如果你想*嘗試*保留你已經擁有的任何數據(這可能是也可能不是這里)。

以下將按預期創建索引並執行您嘗試運行的suggest查詢。 請注意,我已將查詢范圍限定為僅針對索引myindex運行。 類型

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
}

這會將以下內容注銷到控制台

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}}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM