Elasticsearch NEST: ordering terms with multiple criteria
Using NEST, I need to be able to order the aggregation of terms with multiple criteria (ElasticSearch 1.5 or newer required). For example:
"order": [{"avg_rank": "desc"}, {"avg_score": "desc"}]
This works great using the original JSON I created to test that I was getting the expected behavior. Now trying to translate this to code using the NEST library, I can't see how this would be accomplished.
The method OrderDescending()
has only one implementation, which takes a string for the key. I need a method of type "params" that can take a list of items OrderDescending()
and / or OrderAscending()
.
- Is there a way to do this in NEST that I am overlooking?
- Is there a way in NEST to get around this where I can add some raw JSON where I need it?
FWIW, I use the "free" style to create my queries.
EDIT: I see that using the object initializer syntax I could manually create a dictionary and add criteria elements. The problem is that I have a lot of code written in "free" syntax. Thus,
- Is there a way to use an "object initializer" object and convert it to a "free" descriptor? In this case, does Term Aggregator refer to the term Aggregation?
EDIT 2:
First I had to mention that I already tried it .OrderDescending("avg_rank").OrderDescending("avg_score")
. It just took the last link in the chain. Looking at the code, I can see why. Each call will OrderDescending
blindly publish the dictionary instead of checking if it has already been created and adding a new key to the dictionary if it already exists.
Based on this, I believe this is a bug for which I have introduced a report here: OrderDescending and OrderAscending cannot be linked for multi-criteria order
EDIT 3: I appreciate all of the replies (some of them are being removed) because they help manage this and are responsible for making these changes. I also had to mention first that I found that:
"order": { "avg_rank": "desc", "avg_score": "desc" }
does not work. I don't know why exactly, but ES will only use the latter. This is a list of dictionaries as shown in my example above. I have verified that it correctly subscribes the aggregation in the second item. Thus, the underlying object cannot be entered like a simple dictionary. I also added this information to the bug report I created (as pointed out in EDIT 2 ).
source to share
Martijn Laarman of the NEST team was very helpful and helpful to ensure that the bug I reported in EDIT 2 of the description above is addressed. A fix can be found in the comments to the same bug report: Work on ordering the aggregation of the NIST library according to multiple criteria .
Note that it provided work for both the object initializer and fluent syntax (the one I need).
source to share
If you are using fluent syntax, you can simply chain the sorts together.
Example:
var esClient = ninjectKernel.Get<IElasticClient>();
var query = esClient.Search<RedemptionES>(s=> s
.SortAscending(a=>a.Date)
.SortDescending(d=>d.Input.User.Name)
);
Answer:
{
"sort": [
{
"@timestamp": {
"order": "asc"
}
},
{
"input.user.name": {
"order": "desc"
}
}
]
}
source to share