ElasticSearch,简单的两个字段比较无痛
ElasticSearch, simple two fields comparison with painless
我正在尝试 运行 查询 SELECT * FROM indexPeople WHERE info.Age > info.AgeExpectancy
请注意,这两个字段 未嵌套 ,它们只是 json 对象
POST /indexPeople/_search
{
"from" : 0,
"size" : 200,
"query" : {
"bool" : {
"filter" : [
{
"bool" : {
"must" : [
{
"script" : {
"script" : {
"source" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
"lang" : "painless"
},
"boost" : 1.0
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"_source" : {
"includes" : [
"info"
],
"excludes" : [ ]
}
}
但是这个查询失败了
{
"error" : {
"root_cause" : [
{
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
"doc['info.Age'].value > doc['info.AgeExpectancy'].value",
" ^---- HERE"
],
"script" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
"lang" : "painless",
"position" : {
"offset" : 22,
"start" : 0,
"end" : 70
}
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "indexPeople",
"node" : "c_Dv3IrlQmyvIVpLoR9qVA",
"reason" : {
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
"doc['info.Age'].value > doc['info.AgeExpectancy'].value",
" ^---- HERE"
],
"script" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
"lang" : "painless",
"position" : {
"offset" : 22,
"start" : 0,
"end" : 70
},
"caused_by" : {
"type" : "illegal_state_exception",
"reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
}
}
}
]
},
"status" : 400
}
有办法实现吗?
调试它的最佳方法是什么?我想打印对象或查看日志(不存在),但我无法找到两者兼顾的方法。
映射是:
{
"mappings": {
"_doc": {
"properties": {
"info": {
"properties": {
"Age": {
"type": "long"
},
"AgeExpectancy": {
"type": "long"
}
}
}
}
}
}
}
也许您已经解决了这个问题。查询失败的原因很明确:
"caused_by" : {
"type" : "illegal_state_exception",
"reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
}
基本上有一个或多个文档没有一个查询字段。因此,您可以通过使用 if 检查字段是否确实存在来获得所需的结果。如果它们不存在,您可以简单地 return false 如下:
{
"script": """
if (doc['info.Age'].size() > 0 && doc['info.AgeExpectancy'].size() > 0) {
return doc['info.Age'].value > doc['info.AgeExpectancy'].value
}
return false;
}
"""
我使用 Elasticsearch 7.10.2 对其进行了测试,它可以正常工作。
最好的调试方法是什么
这是一个思考问题,也许有人对此有更好的答案。我尝试列出一些选项。显然,调试需要仔细阅读错误信息。
无痛实验室
如果您有最新版本的 Kibana,您可以尝试使用无痛实验室来模拟您的文档,并在更集中的环境中更快地发现错误。
KIBANA 脚本字段
您可以尝试在名为条件的索引模式中创建一个布尔脚本字段。点击创建前记得点击“预览结果”:
最小示例 创建一个最小示例以降低复杂性。
对于这个答案,我使用了一个示例索引,其中包含四个文档以及所有可能的案例。
- 无信息:
{ "message": "ok"}
- Info.Age 但不是预期年龄:
{"message":"ok","info":{"Age":14}}
- Info.Age预期而非年龄:
{"message":"ok","info":{"AgeExpectancy":12}}
- Info.Age 和预期年龄:
{"message":"ok","info":{"Age":14, "AgeExpectancy": 12}}
我正在尝试 运行 查询 SELECT * FROM indexPeople WHERE info.Age > info.AgeExpectancy
请注意,这两个字段 未嵌套 ,它们只是 json 对象
POST /indexPeople/_search
{
"from" : 0,
"size" : 200,
"query" : {
"bool" : {
"filter" : [
{
"bool" : {
"must" : [
{
"script" : {
"script" : {
"source" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
"lang" : "painless"
},
"boost" : 1.0
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"_source" : {
"includes" : [
"info"
],
"excludes" : [ ]
}
}
但是这个查询失败了
{
"error" : {
"root_cause" : [
{
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
"doc['info.Age'].value > doc['info.AgeExpectancy'].value",
" ^---- HERE"
],
"script" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
"lang" : "painless",
"position" : {
"offset" : 22,
"start" : 0,
"end" : 70
}
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "indexPeople",
"node" : "c_Dv3IrlQmyvIVpLoR9qVA",
"reason" : {
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
"doc['info.Age'].value > doc['info.AgeExpectancy'].value",
" ^---- HERE"
],
"script" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
"lang" : "painless",
"position" : {
"offset" : 22,
"start" : 0,
"end" : 70
},
"caused_by" : {
"type" : "illegal_state_exception",
"reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
}
}
}
]
},
"status" : 400
}
有办法实现吗? 调试它的最佳方法是什么?我想打印对象或查看日志(不存在),但我无法找到两者兼顾的方法。
映射是:
{
"mappings": {
"_doc": {
"properties": {
"info": {
"properties": {
"Age": {
"type": "long"
},
"AgeExpectancy": {
"type": "long"
}
}
}
}
}
}
}
也许您已经解决了这个问题。查询失败的原因很明确:
"caused_by" : {
"type" : "illegal_state_exception",
"reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
}
基本上有一个或多个文档没有一个查询字段。因此,您可以通过使用 if 检查字段是否确实存在来获得所需的结果。如果它们不存在,您可以简单地 return false 如下:
{
"script": """
if (doc['info.Age'].size() > 0 && doc['info.AgeExpectancy'].size() > 0) {
return doc['info.Age'].value > doc['info.AgeExpectancy'].value
}
return false;
}
"""
我使用 Elasticsearch 7.10.2 对其进行了测试,它可以正常工作。
最好的调试方法是什么
这是一个思考问题,也许有人对此有更好的答案。我尝试列出一些选项。显然,调试需要仔细阅读错误信息。
无痛实验室 如果您有最新版本的 Kibana,您可以尝试使用无痛实验室来模拟您的文档,并在更集中的环境中更快地发现错误。
KIBANA 脚本字段
您可以尝试在名为条件的索引模式中创建一个布尔脚本字段。点击创建前记得点击“预览结果”:
最小示例 创建一个最小示例以降低复杂性。 对于这个答案,我使用了一个示例索引,其中包含四个文档以及所有可能的案例。
- 无信息:
{ "message": "ok"}
- Info.Age 但不是预期年龄:
{"message":"ok","info":{"Age":14}}
- Info.Age预期而非年龄:
{"message":"ok","info":{"AgeExpectancy":12}}
- Info.Age 和预期年龄:
{"message":"ok","info":{"Age":14, "AgeExpectancy": 12}}