文档没有字段值!使用 doc[<field>].size()==0 检查文档是否缺少字段
A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field
当我 运行 以下查询时:
GET /annotations/_search
{
"query": {
"match_all": {}
}
}
我收到以下回复:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "annotations",
"_type" : "_doc",
"_id" : "I9nlA",
"_score" : 1.0,
"_source" : {
"preferences" : {
"id" : 1,
"annotation_id" : "I9nlA",
"answer_timer" : 24
}
// other fields here
}
},
{
"_index" : "annotations",
"_type" : "_doc",
"_id" : "XIP6L",
"_score" : 1.0,
"_source" : {
"id" : "XIP6L",
"preferences" : {
"id" : 2,
"annotation_id" : "XIP6L",
"answer_timer" : 5
},
// other fields here
}
}
]
}
}
如您所见,字段 Preferences
没有空值。
我的问题是,当我添加基于 Preferences
字段的脚本字段时,它会引发错误。
查询:
GET /annotations/_search
{
"query": {
"match_all": {}
},
"script_fields": {
"can_answer": {
"script": {
"source": """
if (doc['creator_id'].value == params['user_id']){
return true;
}
else{
String nowString = params['now'];
ZonedDateTime now = ZonedDateTime.parse(nowString);
ZonedDateTime created = doc['created'].value;
ZonedDateTime createdPlusAnswerTimer = created.plusHours(
doc['preferences.answer_timer'].value
);
Duration d = Duration.between(now, createdPlusAnswerTimer);
return d.toHours() > 0;
}
""",
"params": {
"user_id": 1,
"now": "2022-05-17T16:17:49.366Z"
}
}
}
}
}
错误:
{
"error" : {
"root_cause" : [
{
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues.throwIfEmpty(ScriptDocValues.java:73)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:118)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:113)",
"createdPlusAnswerTimer = created.plusHours(\n doc['preferences.answer_timer'].value\n );\n Duration ",
" ^---- HERE"
],
"script" : " ...",
"lang" : "painless",
"position" : {
"offset" : 398,
"start" : 309,
"end" : 441
}
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "annotations",
"node" : "_ljs4uLdR7eBjL8ioYLqAg",
"reason" : {
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues.throwIfEmpty(ScriptDocValues.java:73)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:118)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:113)",
"createdPlusAnswerTimer = created.plusHours(\n doc['preferences.answer_timer'].value\n );\n Duration ",
" ^---- HERE"
],
"script" : " ...",
"lang" : "painless",
"position" : {
"offset" : 398,
"start" : 309,
"end" : 441
},
"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
}
说doc['preferences.answer_timer'].value
有问题,不知道是什么原因。该字段在所有文档中都有值。
问题是什么,我该如何解决?
谢谢。
更新:已添加映射:
{
"annotations" : {
"mappings" : {
"properties" : {
// other fields
"preferences" : {
"type" : "nested",
"properties" : {
"annotation_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"answer_timer" : {
"type" : "long"
},
"id" : {
"type" : "long"
}
}
}
// other fields
}
}
}
}
注意
当我使用 params._source.preferences.answer_timer
时,它工作正常。但是在Elasticsearch的文档中,说使用_source.field
很慢,所以我不想使用它。
由于preferences
字段是嵌套的,我们需要在嵌套查询的上下文中调用脚本。父文档没有 doc_value 字段 - 因此会出错。参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
解决方案 1:将 preferences
类型更改为 object
而不是嵌套。
解决方案 2:在嵌套上下文中使用查询。
当我 运行 以下查询时:
GET /annotations/_search
{
"query": {
"match_all": {}
}
}
我收到以下回复:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "annotations",
"_type" : "_doc",
"_id" : "I9nlA",
"_score" : 1.0,
"_source" : {
"preferences" : {
"id" : 1,
"annotation_id" : "I9nlA",
"answer_timer" : 24
}
// other fields here
}
},
{
"_index" : "annotations",
"_type" : "_doc",
"_id" : "XIP6L",
"_score" : 1.0,
"_source" : {
"id" : "XIP6L",
"preferences" : {
"id" : 2,
"annotation_id" : "XIP6L",
"answer_timer" : 5
},
// other fields here
}
}
]
}
}
如您所见,字段 Preferences
没有空值。
我的问题是,当我添加基于 Preferences
字段的脚本字段时,它会引发错误。
查询:
GET /annotations/_search
{
"query": {
"match_all": {}
},
"script_fields": {
"can_answer": {
"script": {
"source": """
if (doc['creator_id'].value == params['user_id']){
return true;
}
else{
String nowString = params['now'];
ZonedDateTime now = ZonedDateTime.parse(nowString);
ZonedDateTime created = doc['created'].value;
ZonedDateTime createdPlusAnswerTimer = created.plusHours(
doc['preferences.answer_timer'].value
);
Duration d = Duration.between(now, createdPlusAnswerTimer);
return d.toHours() > 0;
}
""",
"params": {
"user_id": 1,
"now": "2022-05-17T16:17:49.366Z"
}
}
}
}
}
错误:
{
"error" : {
"root_cause" : [
{
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues.throwIfEmpty(ScriptDocValues.java:73)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:118)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:113)",
"createdPlusAnswerTimer = created.plusHours(\n doc['preferences.answer_timer'].value\n );\n Duration ",
" ^---- HERE"
],
"script" : " ...",
"lang" : "painless",
"position" : {
"offset" : 398,
"start" : 309,
"end" : 441
}
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "annotations",
"node" : "_ljs4uLdR7eBjL8ioYLqAg",
"reason" : {
"type" : "script_exception",
"reason" : "runtime error",
"script_stack" : [
"org.elasticsearch.index.fielddata.ScriptDocValues.throwIfEmpty(ScriptDocValues.java:73)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:118)",
"org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:113)",
"createdPlusAnswerTimer = created.plusHours(\n doc['preferences.answer_timer'].value\n );\n Duration ",
" ^---- HERE"
],
"script" : " ...",
"lang" : "painless",
"position" : {
"offset" : 398,
"start" : 309,
"end" : 441
},
"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
}
说doc['preferences.answer_timer'].value
有问题,不知道是什么原因。该字段在所有文档中都有值。
问题是什么,我该如何解决? 谢谢。
更新:已添加映射:
{
"annotations" : {
"mappings" : {
"properties" : {
// other fields
"preferences" : {
"type" : "nested",
"properties" : {
"annotation_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"answer_timer" : {
"type" : "long"
},
"id" : {
"type" : "long"
}
}
}
// other fields
}
}
}
}
注意
当我使用 params._source.preferences.answer_timer
时,它工作正常。但是在Elasticsearch的文档中,说使用_source.field
很慢,所以我不想使用它。
由于preferences
字段是嵌套的,我们需要在嵌套查询的上下文中调用脚本。父文档没有 doc_value 字段 - 因此会出错。参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
解决方案 1:将 preferences
类型更改为 object
而不是嵌套。
解决方案 2:在嵌套上下文中使用查询。