我是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组
任何人都知道,为什么我试图获得单个列的结果时会遇到异常?
如果您知道解决方案,请与我分享。
答案 0 :(得分:0)
在使用pyodbc
和ElasticSearch进行了几次实验之后,我得出了以下结论:
_score
上进行聚合,并且不允许用户这样做_score
计算聚合的行为很可能是一个错误,不是由ElasticSearch执行,而是由驱动程序执行。简而言之,不要将_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驱动程序is aware of _score
field:
选择_score列后,将请求评分 发出查询上下文请求,对其质量进行评分 搜索结果。默认情况下,结果按降序返回 基于计算的_score。可以指定ORDER BY子句 更改返回结果的顺序。
如果未选择_score列,将发送过滤器上下文, 在这种情况下,Elasticsearch不会计算分数。结果为 除非是ORDER BY,否则这些查询将以任意顺序返回 子句是明确指定的。
基本上,这意味着通过在查询中明确提及_score
将使ODBC返回此类字段(默认情况下可能存在)。
我安装了pyodbc并在我的localhost上设置了ElasticSearch 5.4。我调整了ES以记录它收到的所有查询。
首先我复制了第一个案例:
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}
接下来我接受了第二个查询:
cursor.execute("SELECT _id, sum(_score) FROM my_index.my_type GROUP BY _id")
无异常执行但导致此ES查询:
{"from":0,"size":10000,"_source":{"includes":["_id","_score"],"excludes":[]}}
然后我尝试用非现有字段模拟库:
cursor.execute("SELECT sum(score42) FROM simple_index.simple_type")
在这种情况下,例外是不同的:
[HY000] 'score42' is not a valid column.
虽然发送给ES的查询与第一种情况相同。
然后我试图找出库如何发送聚合请求:
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
和"工作"上进行汇总这里的案例可能是一个错误。