elasticsearch query text field with length of value more than 20 - elasticsearch

I would like to query name filed with length of value(text) is more than 20 by using the following but not working:
GET /groups/_search
{
"query": {
"bool" : {
"must" : {
"script" : {
"script" : "_source.name.values.length() > 20"
}
}
}
}
}
the error msg is :
{
"error": {
"root_cause": [
{
"type": "script_exception",
"reason": "compile error",
"script_stack": [
"_source.name.values.lengt ...",
"^---- HERE"
],
"script": "_source.name.values.length() > 5",
"lang": "painless"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "groups",
"node": "exBbDVGeToSDRzLLmOh8-g",
"reason": {
"type": "query_shard_exception",
"reason": "failed to create query: {\n \"bool\" : {\n \"must\" : [\n {\n \"script\" : {\n \"script\" : {\n \"inline\" : \"_source.name.values.length() > 5\",\n \"lang\" : \"painless\"\n },\n \"boost\" : 1.0\n }\n }\n ],\n \"disable_coord\" : false,\n \"adjust_pure_negative\" : true,\n \"boost\" : 1.0\n }\n}",
"index_uuid": "_VH1OfpdRhmd_UPV7uTNMg",
"index": "groups",
"caused_by": {
"type": "script_exception",
"reason": "compile error",
"script_stack": [
"_source.name.values.lengt ...",
"^---- HERE"
],
"script": "_source.name.values.length() > ",
"lang": "painless",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Variable [_source] is not defined."
}
}
}
}
]
},
"status": 400
}
no idea how should i fix it...
fyi: version of es is 5.4.0
I don't know the following issue related:
Painless script_fields don't have access to a _source variable #20068
https://github.com/elastic/elasticsearch/issues/20068

The best and most optimal way to handle this is to also index another field with the length of the name field, let's call it nameLength. That way you shift the burden of computing the length of the name field at indexing time instead of having to do it (repeatedly) at query time.
So at indexing time if you have a name field like {"name": "A big brown fox"}, then you create a new field with the length of the name field, such as {"name": "A big brown fox", "nameLength": 15}.
At query time, you'll be able to use a simple and quick range query on the nameLength field:
GET /groups/_search
{
"query": {
"bool" : {
"must" : {
"range" : {
"nameLength": {
"gt": 20
}
}
}
}
}
}

You can use:
params._source.name.length() > 20
In case this is a rare query, that's probably ok to do. Otherwise you should add a field for the name length, and use the range query.

Related

Elasticsearch mixed number and string multi_match query failing

I am trying to build a query where I can accept a string containing strings and numbers, and search for those values in fields in my index that contain double values and strings. For example:
Fields: Double doubleVal, String stringVal0, String stringVal1, String doNotSearchVal
Example search string: "person 10"
I am trying to get all documents containing "person" or "10" in any of the fields doubleVal, stringVal0 and stringVal1. This is my example query:
{
"query": {
"multi_match" : {
"query": "person 10",
"fields" : [
"doubleVal^1.0",
"stringVal0^1.0",
"stringVal1^1.0"
],
"type" : "best_fields",
"operator" : "OR",
"slop" : 0,
"prefix_length" : 0,
"max_expansions" : 50,
"zero_terms_query" : "NONE",
"auto_generate_synonyms_phrase_query" : true,
"fuzzy_transpositions" : true,
"boost" : 1.0
}
}
}
(This query was generated by Spring Data Elastic)
When I run this query, I get this error: (I've removed any identifying information)
{
"error": {
"root_cause": [
{
"type": "query_shard_exception",
"reason": "failed to create query: [query removed]",
"index_uuid": "index_uuid",
"index": "index_name"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "index_name",
"node": "node_value",
"reason": {
"type": "query_shard_exception",
"reason": "failed to create query: [query removed]",
"index_uuid": "index_uuid",
"index": "index_name",
"caused_by": {
"type": "number_format_exception",
"reason": "For input string: \"person 10\""
}
}
}
]
},
"status": 400
}
I do not want to split apart the search string. If there is a way to rewrite the query so that it works in the expected way, I would like to do it that way.
You should try to set parameter lenient to true, then format-based errors, such as providing a text query value for a numeric field, will be ignored
You could achieve this in Spring Data with using builder method like this:
.lenient(true)

Script update with array method unique() causing error

I need to update array value with another array and then remove intersections, so I found this method 'unique()' for elasticsearch scripts, but it's causing error:
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[probook][127.0.0.1:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"ctx._source.arrFieldName = ctx._source.arrFieldName.unique();",
" ^---- HERE"
],
"script": "ctx._source.arrFieldName.addAll([111, 222, 333]);ctx._source.arrFieldName = ctx._source.arrFieldName.unique();ctx._source.arrFieldNameCount = ctx._source.arrFieldName.length",
"lang": "painless",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "dynamic method [java.util.ArrayList, unique/0] not found"
}
}
},
"status": 400
}
You should do it this way with distinct() instead of unique() for your inline painless script,
{
"script" : {
"inline": "ctx._source.arrFieldName=
ctx._source.arrFieldName.stream().distinct().sorted()
.collect(Collectors.toList())"
}
}

Upserts with a script gives me a null pointer exception

I am new to elastic search and I am testing the starter commands. I created an Index, added a document updated it with a simple update. now I am trying to make a scripted update with an upsert tag in the post request. I receiv a null pointr exception as shown below.
POST products/_update/1
{
"script" :"ctx._source.price += 5",
"upsert" : {
"price" : 1
}
}
I received the following instead of success
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[DESKTOP-IGOE2EN][127.0.0.1:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"ctx._source.price += 5",
" ^---- HERE"
],
"script": "ctx._source.price += 5",
"lang": "painless",
"caused_by": {
"type": "null_pointer_exception",
"reason": null
}
}
},
"status": 400
}
I think you should add a condition to check if the field (price) exists before accessing it by adding a if() condition:
POST products/_update/1
{
"script" :"if(ctx._source.price!= null) {ctx._source.price += 5"},
"upsert" : {
"price" : 1
}
}

Elasticsearch script query array field size comparison

Is it possible to make a comparison with respect to the length of an array field in Elasticsearch?
For instance the following works (sourceId is a text type field)
GET /entity_active/_count
{
"query": {
"bool" : {
"must" : {
"script" : {
"script" : {
"inline": "doc['sourceId'].values.size() > 0",
"lang": "painless"
}
}
}
}
}
}
However the following does not work (users is an array field)
GET /entity_active/_count
{
"query": {
"bool" : {
"must" : {
"script" : {
"script" : {
"inline": "doc['users'].values.size() > 0",
"lang": "painless"
}
}
}
}
}
}
The latter returns such a response:
"error": {
"root_cause": [
{
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:80)",
"doc['users'].values.size() > 0",
" ^---- HERE"
],
"script": "doc['users'].values.size() > 0",
"lang": "painless"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
Do I need to use an alternative way to make use of such array fields?
Arrays are not indexed in ES, hence you cannot access an array via doc_values (i.e. through doc.). You can access the _source document in which the array is present, though, using ctx._source. Try this script instead:
_source.users.size() > 0
or
_source.users.length > 0

Map params is reordered in elasticsearch

I have a query using script to sort the result, for my business, I need one params named cities to calculate the sort value, but when I use Debug.explain to print the params.cities, the order is not unexpected, it's reordered.
Is there anyone know how to use the correct order in script? thanks in advance for your help.
Query:
GET tour/product/_search
{
"sort" : [
{
"_script" : {
"script" : {
"inline" : "Debug.explain(params.cities);",
"lang" : "painless",
"params" : {
"cities" : {
"2" : 100.0,
"17" : 3.71,
"12" : 3.63,
"13" : 3.63,
"14" : 3.6
}
}
},
"type" : "number",
"order" : "desc"
}
}
]
}
Print result:
{ "error": {
"root_cause": [
{
"type": "painless_explain_error",
"reason": "painless_explain_error: null"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "tour-1",
"node": "y5z7ah5cSoCk6n3Q95gbxw",
"reason": {
"type": "script_exception",
"reason": "runtime error",
"painless_class": "HashMap",
"to_string": "{12=3.63, 2=100.0, 13=3.63, 14=3.6, 17=3.71}",
"java_class": "java.util.HashMap",
"script_stack": [
"Debug.explain(params.cities);",
" ^---- HERE"
],
"script": "Debug.explain(params.cities);",
"lang": "painless",
"caused_by": {
"type": "painless_explain_error",
"reason": "painless_explain_error: null"
}
}
}
],
"caused_by": {
"type": "script_exception",
"reason": "runtime error",
"painless_class": "HashMap",
"to_string": "{12=3.63, 2=100.0, 13=3.63, 14=3.6, 17=3.71}",
"java_class": "java.util.HashMap",
"script_stack": [
"Debug.explain(params.cities);",
" ^---- HERE"
],
"script": "Debug.explain(params.cities);",
"lang": "painless",
"caused_by": {
"type": "painless_explain_error",
"reason": "painless_explain_error: null"
}
} }, "status": 500 }

Resources