当我执行以下查询时:
{
"query": {
"bool": {
"filter": [
{
"match": {
"my_value": "hi"
}
},
{
"range": {
"my_range": {
"gt": 0,
"lte": 200
}
}
}
]
}
},
"sort": {
"my_range": {
"order": "asc",
"mode": "min"
}
}
}
我得到了错误:
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Fielddata is not supported on field [my_range] of type [long_range]"
}
如何使range
数据类型可排序?这可能吗?
Elasticsearch版本:5.4,但是我想知道是否可以使用任何版本。
更多上下文
并非别名/索引中的所有文档都具有range字段。但是,查询过滤器仅包括具有该字段的文档。
答案 0 :(得分:1)
使用范围数据类型的字段进行排序不是直接的。仍然可以在某种程度上使用script based sorting以获得预期的结果。
例如为了简化脚本,我假设对于您所有的文档,针对my_range
字段编制索引的数据仅包含gt
和lte
的数据,并且您希望基于以下参数的最小值进行排序两个,然后您可以添加以下内容进行排序:
{
"query": {
"bool": {
"filter": [
{
"match": {
"my_value": "hi"
}
},
{
"range": {
"my_range": {
"gt": 0,
"lte": 200
}
}
}
]
}
},
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"inline": "Math.min(params['_source']['my_range']['gt'], params['_source']['my_range']['lte'])"
},
"order": "asc"
}
}
}
您可以根据需要将所有lt
,gt
,lte
,gte
组合在一起的复杂数据来修改脚本。
更新(用于其他不同用例的脚本):
1。按差异排序"Math.abs(params['_source']['my_range']['gt'] - params['_source']['my_range']['lte'])"
2。按gt
排序
"params['_source']['my_range']['gt']"
3。按lte
排序
"params['_source']['my_range']['lte']"
4。如果查询返回的文档很少,则没有range
字段
"if(params['_source']['my_range'] != null) { <sorting logic> } else { return 0; }"
将<sorting logic>
替换为所需的排序逻辑(可以是以上3种之一或查询中的一种)
return 0
可以替换为return -1
或其他根据排序需要的数字
答案 1 :(得分:1)
我认为您正在寻找的是基于difference of the range
的排序方式,我不确定仅对任何范围值进行排序是否有意义。
例如如果一个文档的范围是100, 300
,而另一文档的范围是200, 600
,则您可能希望根据差异进行排序,例如您可能希望较小的范围出现,即300-100 = 200
出现在顶部。
如果是这样,我已经利用下面的painless script并实现了script based sorting。
POST <your_index_name>/_search
{
"query":{
"match_all":{
}
},
"sort":{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":"params._source.my_range.lte-params._source.my_range.gte"
},
"order":"asc"
}
}
}
请注意,在这种情况下,排序将不会基于my_range
的任何字段值,而只会基于它们之间的差异。如果您想基于lte
,lt
,gte
或gt
之类的字段进一步排序,则可以使用以下多个脚本来实现排序:
POST <your_index_name>/_search
{
"query":{
"match_all":{
}
},
"sort":[
{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":"params._source.my_range.lte - params._source.my_range.gte"
},
"order":"asc"
}
},
{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":"params._source.my_range.lte"
},
"order":"asc"
}
}
]
}
因此,在这种情况下,即使对于两个文档,范围是相同的,my_range.lte
较小的文档也会首先显示。
但是,如果您只想基于范围值之一进行排序,则可以使用以下查询。
POST <your_index_name>/_search
{
"query":{
"match_all":{
}
},
"sort":{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":"params._source.my_range.lte"
},
"order":"asc"
}
}
}
这是针对方案 根据范围+ Range.lte或Range.lt中存在的差异进行排序
下面的代码是什么,
my_range
字段Long.MAX_VALUE
。这意味着如果您按asc排序,则应返回此文档
持续。 lte
或lt
,并将该值用作high
。请注意,high
的默认值为Long.MAX_VALUE
。gte
或gt
并将该值用作low
。 low
的默认值为0
。 high - low
值。POST <your_index_name>/_search
{
"size":100,
"query":{
"match_all":{
}
},
"sort":[
{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":"""
if(params._source.my_range==null){
return Long.MAX_VALUE;
} else {
long high = Long.MAX_VALUE;
long low = 0L;
if(params._source.my_range.lte!=null){
high = params._source.my_range.lte;
} else if(params._source.my_range.lt!=null){
high = params._source.my_range.lt;
}
if(params._source.my_range.gte!=null){
low = params._source.my_range.gte;
} else if (params._source.my_range.gt==null){
low = params._source.my_range.gt;
}
return high - low;
}
"""
},
"order":"asc"
}
},
{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":"""
if(params._source.my_range==null){
return Long.MAX_VALUE;
}
long high = Long.MAX_VALUE;
if(params._source.my_range.lte!=null){
high = params._source.my_range.lte;
} else if(params._source.my_range.lt!=null){
high = params._source.my_range.lt;
}
return high;"""
},
"order":"asc"
}
}
]
}
这应该与ES 5.4一起使用。希望对您有帮助!
答案 2 :(得分:0)
可以使用正则表达式间隔过滤器轻松解决此问题:
时间间隔使用时间间隔选项可以使用数字范围, 用尖括号“ <>”括起来。对于字符串:“ foo80”:
foo<1-100> # match
foo<01-100> # match
foo<001-100> # no match
Enabled with the INTERVAL or ALL flags.
{
"query": {
"bool": {
"filter": [
{
"match": {
"my_value": "hi"
}
},
{
"regexp": {
"my_range": {
"value": "<0-200>"
}
}
}
]
}
},
"sort": {
"my_range": {
"order": "asc",
"mode": "min"
}
}
}