Is it possible to access a script_field inside a sort?
I have
search_body["script_fields"] = {
"test": {
"script": {
"lang": "painless",
"inline": skill_rating_algorithm.replace("\n", ""),
"params" : {
"param1": {....}
}
}
}
}
And as sort:
search_body["sort"] = {
"_script": {
"type": "string",
"order": "desc",
"script": {
"lang": "painless",
"inline": "def c = params._fields['test']; return c;",
}
},
"number_of_years_of_experience": {"order": "desc"},
"value.raw": {"order": "asc"},
}
But this only return errors.
I could do a sorting script but i need the value returned in the document as a separate key.
My questions is:
Can i access the script_field "test" inside the sort? (More script_fields will come and i will need different ordering)
Related
I have objects like this:
{
subStatus: {
updatedAt: 3
},
statusUpdatedAt: 1
},
{
subStatus: null,
statusUpdatedAt: 2
}
I need to sort the objects conditionally as follows:
relative to the subStatus.updatedAt field if the subStatus field exists,
or relative to the statusUpdatedAt field if the subStatus field does not exist
If both fields are absent, objects should be sorted to the end of the list
I used the following query:
"sort": {
"_script": {
"type": "number",
"order": "asc",
"script": {
"lang": "painless",
"source": "if(doc['subStatus'].value != null) { return doc['subStatus.updatedAt'].value } else { return doc['statusUpdatedAt'].value }"
}
}
}
But I get an Error: "No field found for [subStatus] in mapping with types []"
Could you advise me how to solve the problem?
Try check by "size".
POST idx_fields/_bulk
{"index":{}}
{"subStatus": { "updatedAt": 3 }, "statusUpdatedAt": 1 }
{"index":{}}
{"subStatus": null, "statusUpdatedAt": 2 }
GET idx_fields/_search
{
"sort": {
"_script": {
"type": "number",
"order": "asc",
"script": {
"lang": "painless",
"source": "if(doc['subStatus.updatedAt'].size() > 0) { return doc['subStatus.updatedAt'].value } else { return doc['statusUpdatedAt'].value }"
}
}
}
}
I need to build elasticsearch query with sorting by field value positioning from an array.
Similar to MySQL:
SELECT * FROM `comments` ORDER BY FIELD(`id`,'17','3','5','12') DESC, id DESC;
or Postgres:
SELECT * FROM comments
LEFT JOIN unnest('{12,5,3,17}'::int[]) WITH ORDINALITY t(id, ord) USING (id) ORDER BY t.ord, id DESC;
You are looking for custom sorting in elasticsearch
it is possible to achieve it via painless script
here is what I do
PUT my_test
{
"mappings": {
"properties": {
"animal": {
"type": "keyword"
}
}
}
}
Populate docs
POST my_test/_doc
{
"animal": "mouse"
}
POST my_test/_doc
{
"animal": "cat"
}
POST my_test/_doc
{
"animal": "dog"
}
Custom sort
GET my_test/_search
{
"query": {
"match_all": {}
},
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "if(params.scores.containsKey(doc['animal'].value)) { return params.scores[doc['animal'].value];} return 100000;",
"params": {
"scores": {
"dog": 0,
"cat": 1,
"mouse": 2
}
}
},
"order": "asc"
}
}
}
Just to compliment the answer above.
You can combine the approach to promote some items to the top and keep the origin sorting by relevance for all other items of the search result.
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "if(params.scores.containsKey(doc['sku'].value)) { return params.scores[doc['sku'].value];} return 10",
"params": {
"scores": {
"3JK76": 0,
"8UF78": 1
}
}
},
"order": "asc"
},
"_score": { "order": "desc" }
}
My ES document model is as follows
"hits": [
{
"_source": {
"variant_group": {
"variant_info": [
{
"name": "Toothpaste",
"inventory": 10
}
],
"type_id": 1365
}
},
]
when I try to execute this query in sorting:
{
"_script": {
"type": "number",
"order": "desc",
"script": {
"lang": "groovy",
"inline": "return doc['variant_group.variant_info'].values.any{ it -> it.inventory > 0 }"
}
}
}
following error is raised
No field found for [variant_group.variant_info] in mapping with types [merchant_variant_group]
I tried using containsKey as follows:
{
"_script": {
"type": "number",
"order": "desc",
"script": {
"lang": "groovy",
"inline": "return doc.containsKey('variant_group.variant_info') ? 1 : 0"
}
}
}
this script block returns 0 and not 1
However, if I execute this:
{
"_script": {
"type": "number",
"order": "desc",
"script": {
"lang": "groovy",
"inline": "return doc.containsKey('variant_group.type_id') ? 1 : 0"
}
}
}
it returns the expected response 1
Is there a gotcha that I'm missing for collection types or is there some issue with my code?
Thanks!
Instead of "doc['variant_group.variant_info']" you should use "doc['variant_group']['variant_info']" or "doc.variant_group.variant_info". I've also had luck with "_source.variant_group.variant_info".
I don't know why, but such pattern worked for me:
I used instead:
"inline": "doc['some_array'].values.size()"
this:
"inline": "doc['some_array.any_field'].size()"
Try:
{
"_script": {
"type": "number",
"order": "desc",
"script": {
"lang": "groovy",
"inline": "return doc['variant_group.variant_info. inventory'].any{ inv -> inv > 0 }"
}
}
}
I want some meta field in elasticsearch script_fields query,
I have tried following two ways but both failed.
First Method:
{
"query": {
"match_all": {}
},
"script_fields": {
"FIELD_NAME": {
"script": {
"lang": "painless",
"source": "params._routing"
}
}
}
}
Second Method:
{
"query": {
"match_all": {}
},
"script_fields": {
"FIELD_NAME": {
"script": {
"lang": "painless",
"source": "params['_routing']"
}
}
}
}
Is there any way to access meta fields i.e. "_routing", "_parent" ?
I'm trying to sort ES documents by combining numeric fields found in the root document with fields found in nested documents. For simplicity let's say I want to sort on doc['score'] + doc['nested.score'].
Example mapping and a couple of data documents are here: http://pastebin.com/9sdMphsR
A naive (and wrong) approach since it tries to access doc['score'] directly is:
POST /testing/stuff/_search
{
"query": {
"match_all": {
}
},
"sort": {
"_script": {
"type": "number",
"mode": "max",
"script": {
"inline": "doc['score'].value + doc['variations.score'].value",
"lang": "expression"
},
"order": "desc",
"nested_path": "variations"
}
}
}
What's the correct way to go about doing this? I realize I could copy the root-level score into each nested document, but if I can avoid doing that I'd prefer to.
POST /testing/stuff/_search
{
"query": {
"match_all": {}
},
"sort": {
"_script": {
"type": "number",
"script": {
"inline": "def max=java.lang.Integer.MIN_VALUE; for(obj in doc['variations.score']){ if (obj > max) max = obj; }; return doc['score'].value + max",
"lang": "groovy"
},
"order": "desc"
}
}
}
And the variations field needs to have "include_in_parent": true for the script to be able to access the nested values.