0

我是 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:'错误 [HY000] '_score' 列不适用于 sum 函数。

但以下查询返回结果:

“选择 _id, sum(_score) from ordersdetails group by _id”

任何人都知道,为什么在尝试获取单个列的结果时出现异常?

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

4

1 回答 1

0

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

  1. CData ODBC 驱动程序知道不可能进行聚合,_score并且不允许用户这样做
  2. 它实际计算聚合的行为_score很可能是一个错误,并且不是由 ElasticSearch 而是由驱动程序执行的。

简而言之,不要使用_scorefor any GROUP BY,它是 ElasticSearch 专门用于相关性排序的一个特殊功能。

一点介绍

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

每个文档的相关性分数由一个称为 _score 的正浮点数表示。_score 越高,文档越相关。

该字段不是文档的一部分,而是为每个查询和每个文档计算的。在 ElasticSearch_score中用于排序。但是,_score 并不总是计算的,例如当需要对现有字段进行排序时:

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

由于该字段是即时计算的,因此无法创建有效的聚合,因此 ElasticSearch 不允许直接这样做。但是,这仍然可以通过在聚合中使用脚本来实现。

CData ODBC 驱动程序知道 _score 字段

CData ODBC 驱动程序知道_score字段

When the _score column is selected, scoring will be requested by issuing a query context request, which scores the quality of the search results. 默认情况下,根据计算的 _score 以降序返回结果。可以指定 ORDER BY 子句来更改返回结果的顺序。

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

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

实验

我安装了 pyodbc 并在我的本地主机上设置了 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为一个特殊的关键字,而且因为它在被要求时没有尝试生成 ES 聚合sum(_score),所以我假设它通常不允许进行聚合,_score这里的“工作”案例是可能是一个错误。

于 2017-10-11T17:39:32.540 回答