2015-10-04 139 views
1

我刚刚开始使用Elasticsearch,并且希望在映射为date,格式为hour_minute的字段上使用基于脚本的排序。每个文档中可以有多个字段的实例。Elasticsearch日期字段上的基于脚本的排序

之前引入的表达,作为第一步,我想一个简单的排序(使用SENSE插件):

POST myIndex/_search 
{ 
    "query": { 
     "match_all": {} 
    }, 
    "sort": { 
     "_script": { 
     "script": "doc[\"someTime\"].value", 
     "lang": "groovy", 
     "type": "date", 
     "order": "asc" 
     } 
    } 
} 

我得到这个错误(片段):

SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; 
shardFailures {[tjWL-zV5QXmGjNlXzLvrzw][myIndex][0]: 
SearchParseException[[myIndex][0]: 
query[ConstantScore(*:*)],from[-1],size[-1]: Parse Failure [Failed to parse source… 

如果我发布上述查询"type": "number"没有错误,虽然这当然不按日期排序。以下工作正常:

POST myIndex/_search 
{ 
    "query": { 
     "match_all": {} 
    }, 
    "sort": { 
     "someTime": { 
     "order": "asc" 
     } 
    } 
} 

最后,我想使用基于脚本的排序,因为我将尝试查询,筛选或排序使用日期和时间条件,如查询与今天的日期的引用文件,然后排序他们通过那就是时间后,现在最低的时间等

任何建议,将不胜感激。

回答

3

使用脚本文件的排序是不是真的高性能,特别是如果你的文档基地,预计随着时间的推移增长。所以我要为此提供一个解决方案,然后提出另一种选择。

为了使用脚本进行排序,您需要将日期转换为毫秒,因此您的排序可以在简单数字上运行(排序类型只能为numberstring)。

POST myIndex/_search 
{ 
    "query": { 
     "match_all": {} 
    }, 
    "sort": { 
     "_script": { 
     "script": "doc[\"someTime\"].date.getMillisOfDay()", 
     "lang": "groovy", 
     "type": "number",  <----- make sure this is number 
     "order": "asc" 
     } 
    } 
} 

请注意,这取决于你想要的粒度,你也可以使用getSecondOfDay()getMinuteOfDay()。这样一来,只要您的查询和过滤器已选择正确的文件一天,你的排序脚本将排序基于该天中的毫秒(或几秒或几分钟)的文件数量。

第二个解决方案将意味着还指数,因为这一天的开始毫秒(或几秒或几分钟)的数量到另一个领域,只是用它来进行排序,这样你就不需要脚本。最重要的是,无论您在搜索时需要什么信息,都可以在索引时间知道,而不是实时计算出来。

举例来说,如果你的someTime字段包含日期2015-10-05T05:34:12.276Z,那么你会与指数的价值20052276,这是

  • 5小时millisOfDay场* 3600000毫秒
  • 34分钟* 60000毫秒
  • 12秒* 1000毫秒
  • +276毫秒

然后你就可以使用排序

POST myIndex/_search 
{ 
    "query": { 
     "range": { 
      "someTime": { 
       "gt": "now" 
      } 
     } 
    }, 
    "sort": { 
     "millisOfDay": { 
     "order": "asc" 
     } 
    } 
} 

请注意,我添加了一个查询仅选择someTime日期现后的文件,所以您将获得在未来的所有文件,但排序按升序millisOfDay,这意味着您将首先从now获得最近的日期。

UPDATE

如果someTime的格式HH:mm,那么你也可以存储其millisOfDay值,例如如果someTime = 17:30然后millisOfDay会(17H * 3600000毫秒)+(30分钟* 60000毫秒)= 6300

那么,你的查询需要使用script过滤器进行返工一点点,像这样:

{ 
    "query": { 
    "filtered": { 
     "filter": { 
     "script": { 
      "script": "doc.millisOfDay.value > new DateTime().millisOfDay" 
     } 
     } 
    } 
    }, 
    "sort": { 
    "millisOfDay": { 
     "order": "asc" 
    } 
    } 
} 
+0

转换对我来说不起作用,也许是因为'someTime'的格式是'hour_minute'(例如“17:30”)......我会继续在这个方向上努力,谢谢。 – michaelbcn