How to extract a param length from painless script - elasticsearch-painless

Hi i wonder how i can extract an array length from painless script?
{
"script": {
"lang": "painless",
"source": "what should be here???) {
"params": {
"plus": ["a","b","c"], //how to retrieve 3 as plus length?
}
}

params is a HashMap, in which plus is an ArrayList.
You can get its length by:
"script": {
"lang": "painless",
"inline": "return params.plus.size()",
"params": {
"plus": ["a","b","c"]
}
}

Related

How to calculate data in elastic search

I am trying to calculate data and assign in same field after search result.
{
query: {
"query_string": {
"query": req.body.query
}
}
}
I am getting search result.
"results": [
{
"_index": "test_index",
"_type": "_doc",
"_id": "34",
"_score": 1.8216469,
"_source": {
"pre_function_area": "100",
"property_id": 46,
"max_benchmark": 0,
}
}
]
Here i want to modified max_benchmark during search. So sending query like as.
{
"query": {
"bool" : {
"must" : {
"query_string": {
"query": "test"
}
},
"filter" : {
"script" : {
"script" : { //Math.round((pow * doc['max_benchmark'].value) * 10) / 10
"lang": "expression",
// "lang": "painless",
"source": "doc['max_benchmark'].value * 5",
}
}
}
}
}
}
but it does not update to field i don't want to update actually field value in elasticsearch. I just want logically change value after search so it will display to user. Basically I am trying to calculate below formula and want to update field.
let months = 0;
if(event_date != "") {
let ai_date = moment();
ai_date.month(obj._source.month);
ai_date.year(obj._source.year);
months = ai_date.diff(event_date, 'months');
}
console.log("months "+months);
let pow = Math.pow(1.009,months);
obj._source.max_benchmark_cal = Math.round((pow * obj._source.max_benchmark) * 10) / 10;
obj._source.min_benchmark_cal = Math.round((pow * obj._source.min_benchmark) * 10) / 10;
} else {
obj._source.max_benchmark_cal = "NA";
obj._source.min_benchmark_cal = "NA";
}
can anyone please help me
your are near the good solution.
The asswer is to use a script field.
You can find the doc here
[https://www.elastic.co/guide/en/elasticsearch/reference/7.8/search-fields.html#script-fields]1
GET /_search
{
"query": {
"match_all": {}
},
"script_fields": {
"test1": {
"script": {
"lang": "painless",
"source": "doc['price'].value * 2"
}
},
"test2": {
"script": {
"lang": "painless",
"source": "doc['price'].value * params.factor",
"params": {
"factor": 2.0
}
}
}
}
}
EDIT: To respond to your comment.
You can not add a field to _source, but you can get the _source and the scripted field by specifying the fields you want in the source. (* are accepted).
As an example:
GET test/_search
{
"query": {
"match_all": {}
},
"_source": "*",
"script_fields": {
"test1": {
"script": {
"lang": "painless",
"source": "if(doc['title.keyword'].size()>0 ){doc['title.keyword'].value}"
}
}
}
}

how to check for key exist in elastic-search painless parameters?

How to check for key exists in painless script map parameters.
In below query check a.toString() key exist in params
I've tried everything but didn't get it to work.
Please help me
mapping :
"id": {
"type": "long"
}
query:
{
"query":{
"bool":{
"filter":[
{
"script": {
"script": {
"lang": "painless",
"params": {
"29232":2541,
"minDistance": 0
},
"source": "def a=doc['id'].getValue();double distance=params[a.toString()]; return distance <= 1000 && distance >= params['minDistance']"
}
}
}
]
}
}
}
The params is just a Java Map object. So, the following checks if the key exists in the params and exits early with a false if it does not exist.
GET test/_search
{
"query":{
"bool":{
"filter":[
{
"script": {
"script": {
"lang": "painless",
"params": {
"29232":2541,
"minDistance": 0
},
"source": """
def a=doc['id'].getValue();
if (!params.containsKey(a.toString())) {
return false;
}
double distance=params[a.toString()];
return distance <= 1000 && distance >= params['minDistance']
"""
}
}
}
]
}
}
}

Elasticsearch painless Query to compare date field value with user input date value

ES index field for a date type looks like
"docdate" : {
"type" : "date",
"fields" : {
"text" : {
"type" : "text",
"analyzer" : "autocomplete"
}
}
}
query should check the docdate value with user input param value passed through query as below.
"script": {
"script": {
"source": "def effecDate=doc['docdate'].value; def sf = new SimpleDateFormat('yyyy-MM-dd'); (sf.parse(params.userdate).after(sf.parse(effecDate)) || (sf.parse(params.userdate) == sf.parse(effecDate)) ",
"lang": "painless",
"params": {
"userdate": "2020-12-01"
}
}
}
getting below casting error.
class_cast_exception: Cannot cast org.elasticsearch.script.JodaCompatibleZonedDateTime to java.lang.String
how to achive this query. no data type to field should be added
You can do it like this:
{
"query": {
"script": {
"script": {
"source": """
def effecDate = doc['effdate'].value.toInstant();
def pickupDate = Instant.parse(params.pickUpDate + 'T00:00:00Z');
return ChronoUnit.DAYS.between(effecDate, pickupDate) >= 0;
""",
"lang": "painless",
"params": {
"pickUpDate": "2019-03-01"
}
}
}
}
}

ElasticSearch Script Fields accessable in sort

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)

Modulo operator in Elasticsearch

How can we write a basic condition to use modulo operator in Elasticsearch?
like
user.created modulo 2 = 0
Unfortunately the example from Andrei Stefan with Groovy syntax is not working on my instances.
Here's the official "expression" syntax you can use as filter that can maybe work more widely:
{
"script": {
"script": {
"source": "(doc['transactionAmount'].value % 2) == value",
"lang": "expression",
"params": {
"value": 0
}
}
}
}
I'm assuming you'd want to do this in a script in Elasticsearch. If so, it would be the same as the Groovy modulo operator:
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "doc['user.created'].value % 2 == 0",
"lang": "groovy"
}
}
}
}
}

Resources