首页 > 解决方案 > 有没有办法像其他编程语言一样用脚本迭代弹性数组文档

问题描述

映射

{
"supply": {
  "properties": {
    "rotation_list": {
      "type": "nested",
      "properties": {
        "project_end_date": {
          "type": "nested",
          "properties": {
            "end_date": {
              "type": "date",
              "format": "yyyy-MM-ddTHH:mm:ss"
            }
          }
        },
        "total_days": {
          "type": "integer"
        }
      }
    }
  }
}}

数据

{"rotation_list": [
{
  "project_end_date": [
    {
      "end_date": "2020-08-07"
    },
    {
      "end_date": "2020-06-07"
    }
  ],
  "total_days": 23
},
{
  "project_end_date": [
    {
      "end_date": "2020-08-07"
    }
  ],
  "total_days": 26
}]}

询问

{"query": {
"bool": {
  "filter": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "rotation_list.project_end_date",
            "query": {
              "script": {
                "script": {
                  "lang": "groovy",
                  "inline": "import  org.elasticsearch.common.logging.*;logger=ESLoggerFactory.getLogger('myscript');def ratable =false;logger.info(doc['rotation_list.project_end_date.end_date'].values)"
                }
              }
            }
          }
        }
      ]
    }
  }
}}}

记录结果

[INFO ][myscript] [1596758400000] [INFO ][myscript] [1591488000000] [INFO ][myscript] [1596758400000]

我不确定为什么会这样。有没有办法像 [1596758400000, 1591488000000] 和 [1596758400000] 那样进行迭代。数据也是这样保存的。我在映射中也提到了嵌套类型。不知道为什么会这样返回。有什么方法可以像我索引的原始文档一样进行迭代。

标签: elasticsearchelasticsearch-5elasticsearch-dsl

解决方案


由于嵌套的性质,在脚本查询中访问嵌套文档的嵌套邻居是不可能的,其中每个(子)文档都被视为单独的文档——无论是在顶层还是在像您的rotation_list.project_end_date.

访问嵌套字段的整个上下文的唯一允许的情况是在内部script_fields——但不幸的是你不能通过它们查询——只能动态构建它们并检索它们:

从上面使用您的映射

GET supply_nested/_search
{
  "script_fields": {
    "combined_end_dates": {
      "script": {
        "lang": "painless",
        "source": "params['_source']['rotation_list'][0]['project_end_date']"
      }
    }
  }
}

只有当rotation_list单独嵌套但不是嵌套时,才能在脚本查询中进行迭代project_end_date。在这里使用 7.x:

PUT supply_non_nested
{
  "mappings": {
    "properties": {
      "rotation_list": {
        "type": "nested",
        "properties": {
          "project_end_date": {
            "type": "object",
            "properties": {
              "end_date": {
                "type": "date",
                "format": "yyyy-MM-dd"
              }
            }
          },
          "total_days": {
            "type": "integer"
          }
        }
      }
    }
  }
}

同步文档:

POST supply_non_nested/_doc
{
  "rotation_list": [
    {
      "project_end_date": [
        {
          "end_date": "2020-08-07"
        },
        {
          "end_date": "2020-06-07"
        }
      ],
      "total_days": 23
    },
    {
      "project_end_date": [
        {
          "end_date": "2020-08-07"
        }
      ],
      "total_days": 26
    }
  ]
}

使用painless而不是查询,groovy因为在这种情况下它更安全且更简洁:

GET supply_non_nested/_search
{
  "query": {
    "bool": {
      "filter": {
        "bool": {
          "must": [
            {
              "nested": {
                "path": "rotation_list",
                "query": {
                  "script": {
                    "script": {
                      "lang": "painless",
                      "inline": "Debug.explain(doc['rotation_list.project_end_date.end_date'])"
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
  }
}

屈服

...
"reason": {
          ...
          "to_string": "[2020-06-07T00:00:00.000Z, 2020-08-07T00:00:00.000Z]",
          "java_class": "org.elasticsearch.index.fielddata.ScriptDocValues$Dates",
        }
...

从您的代码段中,您在查询中试图实现的目标并不完全清楚。你能详细说明吗?


推荐阅读