全部, 我正在尝试调用ES 6.6中定义的SearchTemplate。该模板具有分页变量(来自和大小)和我在数组中传递的电子邮件。这也具有使用自定义脚本逻辑进行排序的功能。当我在kibana中运行此程序时,我看不到分页和排序不起作用。我将不胜感激,以使其能够正常工作。请在下面查看详细信息。我使用索引别名搜索两个索引。
人和来宾索引的映射相同(仅是为了使示例简单)
索引映射
PUT _template/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"
},"email": {
"type": "keyword"
}
}
}
}
}
SearchTemplate定义
POST _scripts/guest_person_by_email
{
"script": {
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}5{{/size}}",
"sort": [
{
"_script": {
"order": "asc",
"type": "number",
"script": "return (doc['type'].value == 'person')? 0 : 1;"
}
},
{
"firstName": {
"order": "asc"
}
},
{
"lastName": {
"order": "asc"
}
}
],
"lang": "mustache",
"source": """
{
"query":{
"bool":{
"filter":{
"terms":{
"email":
{{#toJson}}emails{{/toJson}}
}
}
}
}
}
"""
}
}
使用SearchTemplate进行搜索
GET guest-person/_search/template
{
"id":"guest_person_by_email",
"params": {
"emails":["rennishj@test.com"]
}
}
样本数据
PUT person/_doc/1
{
"firstName": "Rennish",
"lastName": "Joseph",
"email": [
"rennishj@test.com"
],
"type":"person"
}
使用NEST 6.6调用搜索模板
List<string> emails = new List<string>(){"rennishj@test.com"};
var searchResponse = client.SearchTemplate<object>(st => st
.Index("guest-person")
.Id("guest_person_by_email")
.Params(p => p
.Add("emails", emails.ToArray())
.Add("from", 0)
.Add("size", 50)
)
);
观察
我在https://discuss.elastic.co/t/c-nest-5-search-with-template/104074/2处发现了类似的帖子,但好像GetSearchTemplate和PutSearchTemplate在NEST 6.x上已停用
这可以使用搜索模板来完成吗?我们使用一些非常复杂的NEST查询,并且正在远离NEST并使用搜索模板。
答案 0 :(得分:1)
有几个问题
"email"
字段映射"dynamic"
设置为false,但不包含"type"
字段映射,因此脚本排序将失败"source"
中为Put Script 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"
]
}
]
}
}
答案 1 :(得分:0)
添加正确的SearchTemplate(如Russ Cam所指出的那样,在“ 源”下移动分页和排序),以防万一将来有人需要它。
POST _scripts/guest_person_by_email
{
"script": {
"lang": "mustache",
"source": """
{
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}5{{/size}}",
"sort": [
{
"_script": {
"order": "asc",
"type": "number",
"script": "return (doc['type'].value == 'person')? 0 : 1;"
}
},
{
"firstName": {
"order": "asc"
}
},
{
"lastName": {
"order": "asc"
}
}
],
"query":{
"bool":{
"filter":{
"terms":{
"email":
{{#toJson}}emails{{/toJson}}
}
}
}
}
}
"""
}
}