有几个问题
-
索引模板定义
"email"
字段映射两次
-
索引模板集
"dynamic"
错误,但不包含
"type"
字段映射,因此脚本排序将失败
-
整个搜索请求需要在
"source"
对于Put脚本API调用
Nest可以帮助构建正确的搜索请求,并将其作为搜索模板的基础,除了使用客户端的其他一系列原因(如循环请求、自动故障转移和重试等)之外。
这是一个完整的例子
private static void Main()
{
var defaultIndex = "person";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex)
.DefaultTypeName("_doc");
var client = new ElasticClient(settings);
// WARNING: This deletes the index to make this code repeatable.
// You probably want to remove this if copying verbatim
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
var indexTemplateResponse = client.LowLevel.IndicesPutTemplateForAll<PutIndexTemplateResponse>(
"person_guest_template",
@"{
""order"": 0,
""index_patterns"": [""person*"",""guest*""],
""settings"": {
""index"": {
""analysis"": {
""filter"": {
""autoComplete_filter"": {
""type"": ""edge_ngram"",
""min_gram"": ""2"",
""max_gram"": ""20""
}
},
""analyzer"": {
""autoComplete"": {
""filter"": [""lowercase"", ""asciifolding"",""autoComplete_filter""],
""type"": ""custom"",
""tokenizer"": ""whitespace""
},
""default"": {
""filter"": [""lowercase"", ""asciifolding""],
""type"": ""custom"",
""tokenizer"": ""whitespace""
}
}
},
""number_of_shards"": ""3"",
""number_of_replicas"": ""1""
}
},
""mappings"": {
""_doc"": {
""dynamic"": false,
""properties"": {
""firstName"": {
""type"": ""keyword"",
""fields"": {
""search"": {
""type"": ""text"",
""analyzer"": ""autoComplete"",
""search_analyzer"": ""default""
}
}
},
""lastName"": {
""type"": ""keyword"",
""fields"": {
""search"": {
""type"": ""text"",
""analyzer"": ""autoComplete"",
""search_analyzer"": ""default""
}
}
},
""email"": {
""type"": ""keyword""
},
""type"": {
""type"": ""keyword""
}
}
}
}
}");
// build a prototype search request
var searchRequest = new SearchRequest
{
From = 0,
Size = 0,
Sort = new List<ISort>
{
new ScriptSort
{
Order = Nest.SortOrder.Ascending,
Type = "number",
Script = new InlineScript("return (doc['type'].value == 'person')? 0 : 1;")
},
new SortField
{
Field = "firstName",
Order = Nest.SortOrder.Ascending
},
new SortField
{
Field = "lastName",
Order = Nest.SortOrder.Ascending
}
},
Query = new BoolQuery
{
Filter = new QueryContainer[]
{
new TermsQuery
{
Field = "email",
Terms = new[] { "emails" }
}
}
}
};
var json = client.RequestResponseSerializer.SerializeToString(searchRequest);
// create template from prototype search request
var jObject = JsonConvert.DeserializeObject<JObject>(json);
jObject["from"] = "{{from}}{{^from}}0{{/from}}";
jObject["size"] = "{{size}}{{^size}}5{{/size}}";
json = jObject.ToString(Newtonsoft.Json.Formatting.None);
// below is invalid JSON, so can only be constructed with replacement
json = json.Replace("[\"emails\"]", "{{#toJson}}emails{{/toJson}}");
// add search template
var putScriptResponse = client.PutScript("guest_person_by_email", s => s
.Script(sc => sc
.Lang(ScriptLang.Mustache)
.Source(json)
)
);
var person = new Person
{
FirstName = "Rennish",
LastName = "Joseph",
Email = new[] { "rennishj@test.com" }
};
// index document
var indexResponse = client.Index(person, i => i.Id(1).Refresh(Refresh.WaitFor));
// search
var searchResponse = client.SearchTemplate<Person>(s => s
.Id("guest_person_by_email")
.Params(p => p
.Add("emails", person.Email)
.Add("from", 0)
.Add("size", 50)
)
);
}
public class Person
{
public string FirstName {get;set;}
public string LastName { get; set; }
public string[] Email {get;set;}
public string Type {get; set;} = "person";
}
搜索模板请求的结果是
{
"took" : 47,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : null,
"hits" : [
{
"_index" : "person",
"_type" : "_doc",
"_id" : "1",
"_score" : null,
"_source" : {
"firstName" : "Rennish",
"lastName" : "Joseph",
"email" : [
"rennishj@test.com"
],
"type" : "person"
},
"sort" : [
0.0,
"Rennish",
"Joseph"
]
}
]
}
}