问题描述
我需要在我的 .net 代码中使用 Script Fields,以便在 Elasticsearch 上运行一些查询逻辑。 This doc 说:
可以使用 .Fields 在响应中访问脚本字段,类似地 到存储的字段。
为了检索脚本字段结果,我似乎需要遍历结果(如建议的 here 或 here)。我想避免这个循环,并以某种方式在我对 nesT 的 client.search() 的调用中获取数据,它已经填充了一个结果列表。这可能吗?
这是我的电话:
public async Task<List<SomeObj>> GetSomeDocsFromEs()
{
var result = await client.SearchAsync<SomeObj>(s => s
.Index(...)
.Query(...)
.Size(...)
.From(...)
.sort(...)
.ScriptFields(sf => sf
.ScriptField("StoredField1",sc => sc
.source(some Painless script)
)
.ScriptField("StoredField2",sc => sc
.source(some Painless script)
)
.ScriptField("StoredField3",sc => sc
.source(some Painless script)
)
)
.StoredFields(sf => sf
.Fields(
f => f.StoredField1,f => f.StoredField2,f => f.StoredField3
)
)
.source(so => so
.Includes(i => i
.Fields(f => f.SkuEntry.Field1,f => f.SkuEntry.Field2,f => f.SkuEntry.Field3
)
)
)
);
return result.Documents.ToList();
}
解决方法
我想避免这个循环,并以某种方式在我对 NEST 的 client.search() 的调用中获取数据,它已经填充了一个结果列表。这可能吗?
脚本字段对于命中数组中的每个命中返回,因此无法避免对命中进行循环。
示例中的result.Documents
映射到每个文档的 _source
字段,这是发送到 Elasticsearch 并编入索引的原始 JSON 对象。这是 result.Hits.Select(h => h.Source).ToList()
的方便简写。
脚本字段不是 _source
文档的一部分,它们在每次命中的单独字段中返回。 result.Fields
是 result.Hits.Select(h => h.Fields).ToList()
的方便简写。
例如,给定以下查询
var searchResponse = client.Search<Project>(s => s
.ScriptFields(sf => sf
.ScriptField("test1",sc => sc
.Source("doc['numberOfCommits'].value * 2")
)
.ScriptField("test2",sc => sc
.Source("doc['numberOfCommits'].value * params.factor")
.Params(p => p
.Add("factor",2.0)
)
)
)
);
发送以下请求
{
"script_fields": {
"test1": {
"script": {
"source": "doc['numberOfCommits'].value * 2"
}
},"test2": {
"script": {
"source": "doc['numberOfCommits'].value * params.factor","params": {
"factor": 2.0
}
}
}
}
}
JSON 响应是
{
"took" : 26,"timed_out" : false,"_shards" : {
"total" : 2,"successful" : 2,"skipped" : 0,"failed" : 0
},"hits" : {
"total" : {
"value" : 1100,"relation" : "eq"
},"max_score" : 1.0,"hits" : [
{
"_index" : "project","_type" : "_doc","_id" : "Konopelski Inc2032","_score" : 1.0,"_routing" : "Konopelski Inc2032","fields" : {
"test2" : [
308.0
],"test1" : [
308
]
}
},{
"_index" : "project","_id" : "Feest Group2047","_routing" : "Feest Group2047","fields" : {
"test2" : [
1986.0
],"test1" : [
1986
]
}
}
]
}
}
遍历响应中每个命中的脚本字段
foreach (var fields in response.Fields)
{
// do something with test1 and test2 values
var test1 = fields.Value<int>("test1");
var test2 = fields.Value<double>("test2");
}