在进行搜索时,是否可以将函数应用于字段



我想在日期字段上进行Range搜索,该字段现在映射到文本。问题是,该领域已有数据;因此删除索引并重新创建新的CCD_ 2以将字段映射为CCD_。因此,我考虑将一个自定义函数应用于该字段以进行Range搜索。这可能吗?

选项1:无需删除和重新创建整个索引即可更新文档。

如果为索引启用了存储,则可以创建具有正确数据类型的子字段。例如,如果现有字段名称为dateText,则可以按如下方式更新索引映射,并利用逐查询更新来重新索引所有文档。

PUT myindex/_mapping
{
"properties": {
"datetext": {
"type": "text",
"fields": {
"dateField": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"   //<--- change this as per the data
}
}
}
}
}

更新映射后使用按查询更新。

POST myindex/_update_by_query?conflicts=proceed

完成以上操作后,您可以在dateText.dateField上使用范围查询。

选项2:您可以使用脚本查询来处理文本到日期的转换和应用范围逻辑。

使用脚本查询当然是可能的,但您的文本字段需要设置fielddata: true,或者是.keyword类型(例如,作为多字段(,脚本才能访问字段值。

一旦处理好了,让我们假设您的文本字段dateFieldAsText包含以秒为单位的epoch时间戳,并且您希望过滤gte&lte具有人类可读的日期范围。然后,我们可以将所有内容解析为毫秒,然后进行简单的比较:

{
"query": {
"script": {
"script": {
"source": """
def doc_ts_milli = Integer.parseInt(doc['dateFieldAsText'].value) * 1000L;

def df = new SimpleDateFormat("yyyy/MM/dd");
def gte_ts = df.parse(params.gte).getTime();
def lte_ts = df.parse(params.lte).getTime();

return doc_ts_milli >= gte_ts && doc_ts_milli <= lte_ts
""",
"params": {
"gte": "2020/01/01",
"lte": "2021/01/01"
}
}
}
}
}

这方面的挑战是,脚本在每个查询中都会被重新初始化(除非它们被存储(,因此速度很慢。因此,最好的方法是使用新的日期字段更新映射,然后调用_reindex来更新所有文档。不需要删除索引。

现在,这种方法的问题是,这不会影响任何新的、传入的文档。在这种情况下,您可以修改您的摄取过程以同时包含新的日期字段(因此,由于遗留原因,您将有两个具有相同值的字段(,也可以建立一个摄取管道来为您执行此操作(->不需要调整摄取过程(。下面是这样一个管道的例子,尽管设计的目的略有不同。原则是一样的。

最新更新