有没有办法在没有额外循环的情况下反序列化搜索结果中的脚本字段值?

问题描述

我需要在我的 .net 代码中使用 Script Fields,以便在 Elasticsearch 上运行一些查询逻辑。 This doc 说:

可以使用 .Fields 在响应中访问脚本字段,类似地 到存储的字段。

为了检索脚本字段结果,我似乎需要遍历结果(如建议的 herehere)。我想避免这个循环,并以某种方式在我对 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.Fieldsresult.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");
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...