elasticsearch - 如何基于保存的搜索中的日期字段显示到期,过期和未到期

标签 elasticsearch kibana elasticsearch-painless

例如,我在索引中有一个日期字段delivery_datetime,我必须向用户显示当天的特定包裹是今天到期还是到期还是到期
我无法创建单独的字段并进行重新索引,因为它基于当前日期并且每天都在变化,例如,如果我必须在编制索引的同时进行计算,那么我每天都必须重新编制索引,这是不可行的,因为我有很多数据。
我可能使用按查询更新,但是我的索引经常通过Python脚本更新,以为我们这里没有ACID属性,因此会发生版本冲突。
就我所知,我认为我唯一的选择是使用脚本字段。
如果我必须用伪代码编写逻辑:

Due - delivery_datetime.dateOnly == now.dateOnly
Over Due - delivery_datetime.dateOnly < now.dateOnly
Not Due - delivery_datetime.dateOnly > now.dateOnly
以为如果生成CSV,我会有很多数据,我不希望脚本化字段对集群性能产生重大影响。
因此,我需要一些帮助才能有效地在脚本字段中执行此操作,或者如果有任何完全不同的解决方案也将非常有帮助。
如果“脚本字段”是唯一的解决方案,则可以通过提供轻松的脚本来获得帮助。

最佳答案

一旦我们排除了文档更新/更新,基本上就有两种方法可以使用:script_fieldsfilter aggregations
让我们首先假设您的映射类似于:

{
  "mappings": {
    "properties": {
      "delivery_datetime": {
        "type": "object",
        "properties": {
          "dateOnly": {
            "type": "date",
            "format": "dd.MM.yyyy"
          }
        }
      }
    }
  }
}
现在,如果我们按其ID过滤所有包,并想知道它处于哪个到期状态,我们可以创建3个脚本字段,如下所示:
GET parcels/_search
{
  "_source": "timeframe_*",
  "script_fields": {
    "timeframe_due": {
      "script": {
        "source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth == params.nowDayOfMonth",
        "params": {
          "nowDayOfMonth": 8
        }
      }
    },
    "timeframe_overdue": {
      "script": {
        "source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth < params.nowDayOfMonth",
        "params": {
          "nowDayOfMonth": 8
        }
      }
    },
    "timeframe_not_due": {
      "script": {
        "source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth > params.nowDayOfMonth",
        "params": {
          "nowDayOfMonth": 8
        }
      }
    }
  }
}
这将返回以下内容:
...
"fields" : {
  "timeframe_due" : [
    true
  ],
  "timeframe_not_due" : [
    false
  ],
  "timeframe_overdue" : [
    false
  ]
}
这很简单,日期数学有一个明显的弱点,将在下面解决。
另外,我们可以使用3个过滤器聚合,类似地仅过滤出1个有问题的文档,如下所示:
GET parcels/_search
{
  "size": 0,
  "query": {
    "ids": {
      "values": [
        "my_id_thats_due_today"
      ]
    }
  },
  "aggs": {
    "due": {
      "filter": {
        "range": {
          "delivery_datetime.dateOnly": {
            "gte": "now/d",
            "lte": "now/d"
          }
        }
      }
    },
    "overdue": {
      "filter": {
        "range": {
          "delivery_datetime.dateOnly": {
            "lt": "now/d"
          }
        }
      }
    },
    "not_due": {
      "filter": {
        "range": {
          "delivery_datetime.dateOnly": {
            "gt": "now/d"
          }
        }
      }
    }
  }
}
屈服
...
"aggregations" : {
  "overdue" : {
    "doc_count" : 0
  },
  "due" : {
    "doc_count" : 1
  },
  "not_due" : {
    "doc_count" : 0
  }
}
现在,第二种方法的优点如下:
  • 不涉及脚本->执行速度更快。
  • 更为重要的是,您不必担心12月15日晚于11月20日这样的月度数学,但是琐碎的月度比较会产生其他结果。您可以在脚本中实现类似的功能,但是复杂度越高,执行速度就越差。
  • 您可以放弃ID过滤,并在内部仪表板中使用这些汇总计数。甚至有可能是客户仪表板,但普通客户很少会打包很多合理的包裹。
  • 关于elasticsearch - 如何基于保存的搜索中的日期字段显示到期,过期和未到期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64734208/

    相关文章:

    elasticsearch - 如何编写脚本字段以获取状态转换之间的天数

    elasticsearch - Elasticsearch同义词仅适用于特定字段

    java - 多个输入的 Hadoop MapReduce

    java - 无法使用 ElasticSearch Java API 检索嵌套对象

    elasticsearch - 当查询包含 “IN”前缀时,为什么 Elasticsearch 不返回结果?

    elasticsearch - 如何在任何嵌套字段中搜索值?

    使用 NOT 进行 Kibana 搜索

    elasticsearch - 如何列出 Elasticsearch 集群上所有存储的脚本?

    mysql - ELK数据摄取: elasticsearch treat text as boolean even though mapping says type is 'text'