Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elasticsearch: sort by field with null values last

I want sort by name, but keep entries with null or missing price data at the end of the results.

I have tried:

sort: {
    sorting.name: {
        order: "asc"
    },
    prices.minprice.price: {
        missing: "_last"
    }
}

but this only sorts by name.

like image 715
arnoldcoder Avatar asked Apr 18 '15 08:04

arnoldcoder


People also ask

How do you sort NULL last?

If you sort a column with NULL values in ascending order, the NULLs will come first. Alternatively, if you add a DESC keyword to get a descending order, NULLs will appear last.

How do I search for NULL values in Elasticsearch?

A null value cannot be indexed or searched. When a field is set to null , (or an empty array or an array of null values) it is treated as though that field has no values. Replace explicit null values with the term NULL . An empty array does not contain an explicit null , and so won't be replaced with the null_value .

How are NULL values sorted?

Specifying the order of NULL valuesIn an ascending sort, the ASC NULLS FIRST keywords request the default order. In a descending sort, DESC NULLS FIRST specifies that rows with a NULL value in the sort key column precede non-NULL rows in the sorted result set.

What is the default sort order in Elasticsearch?

In Elasticsearch, the relevance score is represented by the floating-point number returned in the search results as the _score , so the default sort order is _score descending.


2 Answers

Actually you could use the missing order.

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html#_missing_values

like image 62
Bruno Casali Avatar answered Oct 16 '22 04:10

Bruno Casali


To do this we can use a custom function score (which is faster than custom script based sorting according to elasticsearch documentation). When price is missing, the numeric value will return 0.

We then sort on score first to split into a section with missing price data, and a section without missing price data, and then sort each of these two sections based on name.

{
    "query": {
        "function_score": {
            "boost_mode": "replace",
            "query": {"match_all": {}},
            "script_score": {
                "script": "doc['price'].value == 0 ? 0 : 1"
            }   
        }
    },
    "sort": [
       "_score",
       "name"
    ]
}
like image 26
dpeacock Avatar answered Oct 16 '22 03:10

dpeacock