如何从ElasticSearch获取得分总和

时间:2017-10-10 02:16:40

标签: elasticsearch odbc nest cdata

我是Elasticsearch的新手。我试图使用CData Elasticsearch ODBC驱动程序从ES获得结果。是否有可能获得得分总和?

我的代码:

OdbcConnection connection = new OdbcConnection("Driver={CData ODBC Driver for Elasticsearch};server=localhost");
        connection.Open();
        string query = "select sum(_score) from ordersdetails";
        OdbcCommand odbcCommand = new OdbcCommand(query, connection);
        OdbcDataReader dataReader = odbcCommand.ExecuteReader();
        DataTable dataTable = new DataTable();
        dataTable.Load(dataReader);
        connection.Close();

我遇到了以下例外情况

System.Data.Odbc.OdbcException:'ERROR [HY000]'_score'列不适用于sum函数。'

但是下面的查询返回结果:

“通过_id”选择_id,sum(_score)来自ordersdetails组

任何人都知道,为什么我试图获得单个列的结果时会遇到异常?

如果您知道解决方案,请与我分享。

1 个答案:

答案 0 :(得分:0)

在使用pyodbc和ElasticSearch进行了几次实验之后,我得出了以下结论:

  1. CData ODBC驱动程序知道无法在_score上进行聚合,并且不允许用户这样做
  2. 实际按_score计算聚合的行为很可能是一个错误,不是由ElasticSearch执行,而是由驱动程序执行。
  3. 简而言之,不要将_score用于任何GROUP BY,这是ElasticSearch专门用于相关性排序的一项特殊功能。

    一点介绍

    正如我在问题的评论中已经提到的,ElasticSearch中的_score衡量文档与给定查询的相关性(参见docs):

      

    每个文件的相关性得分用正数表示   浮点数称为_score。 _score越高,   更相关的文件。

    此字段不是文档的一部分,是针对每个查询和每个文档计算的。在ElasticSearch中_score用于sorting。但是,_score is not always computed,例如在现有字段上排序时需要:

      

    不计算_score,因为它不用于排序。

    由于此字段是即时计算的,因此无法创建有效的聚合,因此ElasticSearch不允许直接使用此字段。但是,这仍然可以通过using scripts in the aggregations实现。

    CData ODBC驱动程序知道_score字段

    CData ODBC驱动程序is aware of _score field

      

    选择_score列后,将请求评分   发出查询上下文请求,对其质量进行评分   搜索结果。默认情况下,结果按降序返回   基于计算的_score。可以指定ORDER BY子句   更改返回结果的顺序。

         

    如果未选择_score列,将发送过滤器上下文,   在这种情况下,Elasticsearch不会计算分数。结果为   除非是ORDER BY,否则这些查询将以任意顺序返回   子句是明确指定的。

    基本上,这意味着通过在查询中明确提及_score将使ODBC返回此类字段(默认情况下可能存在)。

    实验

    我安装了pyodbc并在我的localhost上设置了ElasticSearch 5.4。我调整了ES以记录它收到的所有查询。

    1。

    首先我复制了第一个案例:

    cursor.execute("SELECT sum(_score) FROM my_index.my_type")
    

    并收到了这个例外:

    [HY000] The '_score' column is not applicable to the sum function.
    

    在ES的日志中我抓住了这个查询:

    {"from":0,"size":100}
    

    2

    接下来我接受了第二个查询:

    cursor.execute("SELECT _id, sum(_score) FROM my_index.my_type GROUP BY _id")
    

    无异常执行但导致此ES查询:

    {"from":0,"size":10000,"_source":{"includes":["_id","_score"],"excludes":[]}}
    

    3

    然后我尝试用非现有字段模拟库:

    cursor.execute("SELECT sum(score42) FROM simple_index.simple_type")
    

    在这种情况下,例外是不同的:

    [HY000] 'score42' is not a valid column.
    

    虽然发送给ES的查询与第一种情况相同。

    4

    然后我试图找出库如何发送聚合请求:

    cursor.execute("SELECT sum(likes) FROM simple_index.simple_type GROUP BY likes")
    

    事实上,它确实使用了ES聚合:

    {
      "from": 0,
      "size": 0,
      "aggregations": {
        "likes": {
          "terms": {
            "field": "likes",
            "size": 2147483647,
            "min_doc_count": 1,
            "shard_min_doc_count": 0,
            "show_term_doc_count_error": false,
            "order": [
              {
                "_count": "desc"
              },
              {
                "_term": "asc"
              }
            ]
          },
          "aggregations": {
            "sum_likes": {
              "sum": {
                "field": "likes"
              }
            }
          }
        }
      }
    }
    

    结论

    该库能够将_score识别为特殊关键字,并且还因为它在被要求sum(_score)时未尝试生成ES聚合这一事实,我认为它不允许一般来说,在_score和"工作"上进行汇总这里的案例可能是一个错误。