The use case is that, I want to hide product price(change to 0) if a user is not logged in.
PUT /products
{
"mappings": {
"properties": {
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
POST /products/_doc
{
"price": 101
}
POST /products/_doc
{
"price": 102
}
POST /products/_doc
{
"price": 103
}
I try to use runtime_mapping with the following script, but the result still has the original data.
GET /products/_search
{
"query": {
"match_all": {}
},
"runtime_mappings": {
"price": {
"type": "double",
"script": "if(0 == 1) {emit(333);} else{emit(222);}"
}
}
}
What do I miss? Is it the script condition invalid?
Thanks.
-- Edit --
I expect all the price to be 222. But the original price is returned.
Expected out put:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "products",
"_id" : "XXphNoMBcFxgyV6Mwe1-",
"_score" : 1.0,
"_source" : {
"price" : 222
}
},
{
"_index" : "products",
"_id" : "XnphNoMBcFxgyV6Mye2c",
"_score" : 1.0,
"_source" : {
"price" : 222
}
},
{
"_index" : "products",
"_id" : "X3phNoMBcFxgyV6M0e2W",
"_score" : 1.0,
"_source" : {
"price" : 222
}
},
{
"_index" : "products",
"_id" : "YHphNoMBcFxgyV6M3u0V",
"_score" : 1.0,
"_source" : {
"price" : 222
}
}
]
}
}
Actual output:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "products",
"_id" : "XXphNoMBcFxgyV6Mwe1-",
"_score" : 1.0,
"_source" : {
"price" : 101
}
},
{
"_index" : "products",
"_id" : "XnphNoMBcFxgyV6Mye2c",
"_score" : 1.0,
"_source" : {
"price" : 102
}
},
{
"_index" : "products",
"_id" : "X3phNoMBcFxgyV6M0e2W",
"_score" : 1.0,
"_source" : {
"price" : 105
}
},
{
"_index" : "products",
"_id" : "YHphNoMBcFxgyV6M3u0V",
"_score" : 1.0,
"_source" : {
"price" : 0
}
}
]
}
}
After retry on the example in the official doc, I realized that I missed out the fields key in query body.
GET /products/_search
{
"query": {
"match_all": {}
},
"runtime_mappings": {
"price": {
"type": "double",
"script": "if(0 == 1) {emit(333);} else{emit(222);}"
}
},
"fields": ["price"]
}
Now I get both the original and script fields.
Related
I have a scenario where my search query has to search the phone number and license number that starts with "861". This query output all the phone number and license number that begins with "861" with hits count. The output has a total count of license numbers and phone numbers.
But I am expecting to get the output hits separately for phone and license numbers as below the output
Below is my query and output. Also my expected output is below that.
GET emp_details_new/_search
{
"_source": [],
"min_score": 0.5,
"query": {
"multi_match": {
"query": "861",
"fields": ["phone","licence_num"],
"type": "phrase_prefix"
}
}
}
Output:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 6.5032897,
"hits" : [
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "20",
"_score" : 6.5032897,
"_source" : {
"id" : 20,
"firstname" : "Millard",
"phone" : "1531243932",
"licence_num" : "8616829169"
}
},
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "243",
"_score" : 6.5032897,
"_source" : {
"id" : 243,
"firstname" : "Darbie",
"phone" : "8617323318",
"licence_num" : "9154243943"
}
},
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "252",
"_score" : 6.5032897,
"_source" : {
"id" : 252,
"firstname" : "Angus",
"phone" : "2425841984",
"licence_num" : "8616203799"
}
},
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "777",
"_score" : 6.5032897,
"_source" : {
"id" : 777,
"firstname" : "Julio",
"phone" : "8613789726",
"licence_num" : "1355139833"
}
}
]
}
}
My expected output is to get the separate count for phone number and license number as below.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 6.5032897,
"hits" : [
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "20",
"_score" : 6.5032897,
"_source" : {
"id" : 20,
"licence_num" : "8616829169"
}
},
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "252",
"_score" : 6.5032897,
"_source" : {
"id" : 252,
"licence_num" : "8616203799"
}
}
],
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 6.5032897,
"hits" : [
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "243",
"_score" : 6.5032897,
"_source" : {
"id" : 243,
"phone" : "8617323318"
}
},
{
"_index" : "emp_details_new",
"_type" : "_doc",
"_id" : "777",
"_score" : 6.5032897,
"_source" : {
"id" : 777,
"phone" : "8613789726"
}
}
]
}
}
What I believe to be an option is this:
GET _msearch
{"index": "test"}
{ "_source": ["id", "licence_num"], "min_score": 0.5, "query": { "multi_match": { "query": "861", "fields": ["licence_num"], "type": "phrase_prefix" } }}
{"index": "test"}
{ "_source": ["id", "phone"], "min_score": 0.5, "query": { "multi_match": { "query": "861", "fields": ["phone"], "type": "phrase_prefix" } }}
Response:
"responses" : [
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.2039728,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "eb_apoIBOFCrGsmFSmdS",
"_score" : 1.2039728,
"_source" : {
"licence_num" : "8616829169",
"id" : 20
}
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "e7_apoIBOFCrGsmFVmeW",
"_score" : 1.2039728,
"_source" : {
"licence_num" : "8616203799",
"id" : 252
}
}
]
},
"status" : 200
},
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.2039728,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "er_apoIBOFCrGsmFUGfI",
"_score" : 1.2039728,
"_source" : {
"phone" : "8617323318",
"id" : 243
}
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "fL_apoIBOFCrGsmFXmdO",
"_score" : 1.2039728,
"_source" : {
"phone" : "8613789726",
"id" : 777
}
}
]
},
"status" : 200
}
]
I want unique record by merchant.id (nested field) for which I've applied aggs and also I need sorted record by merchant distance for which I've applied nested aggs. My whole query becomes:
{
"size": 0,
"aggs": {
"nested_merchant": {
"nested": {
"path": "merchant"
},
"aggs": {
"group_by_merchant": {
"terms": {
"field": "merchant.id",
"size": 5
},
"aggs": {
"reverse_merchant": {
"reverse_nested": {},
"aggs": {
"hits": {
"top_hits": {
"_source": [
"id",
"title",
"merchant.id"
],
"sort": {
"_geo_distance": {
"location": {
"lat": "24.8185561",
"lon": "67.0399761"
},
"order": "asc",
"unit": "km"
}
},
"size": 1
}
}
}
}
}
}
}
}
}
}
The problem is sorting is not working as expected which is applied by _geo_distance under nested top_hits aggs. Following are the response of the above query.
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 206,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"nested_merchant" : {
"doc_count" : 206,
"group_by_merchant" : {
"doc_count_error_upper_bound" : 5,
"sum_other_doc_count" : 140,
"buckets" : [
{
"key" : 1050,
"doc_count" : 31,
"reverse_merchant" : {
"doc_count" : 31,
"hits" : {
"hits" : {
"total" : {
"value" : 31,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "merchants-ops-qa",
"_type" : "_doc",
"_id" : "3",
"_score" : null,
"_source" : {
"merchant" : {
"id" : 1050
},
"id" : 3,
"title" : "KFC"
},
"sort" : [
0.7493199712361772
]
}
]
}
}
}
},
{
"key" : 1109,
"doc_count" : 11,
"reverse_merchant" : {
"doc_count" : 11,
"hits" : {
"hits" : {
"total" : {
"value" : 11,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "merchants-ops-qa",
"_type" : "_doc",
"_id" : "229",
"_score" : null,
"_source" : {
"merchant" : {
"id" : 1109
},
"id" : 229,
"title" : "Juice Buzz"
},
"sort" : [
0.07126207274611283
]
}
]
}
}
}
},
{
"key" : 1053,
"doc_count" : 8,
"reverse_merchant" : {
"doc_count" : 8,
"hits" : {
"hits" : {
"total" : {
"value" : 8,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "merchants-ops-qa",
"_type" : "_doc",
"_id" : "47",
"_score" : null,
"_source" : {
"merchant" : {
"id" : 1053
},
"id" : 47,
"title" : "Sufi"
},
"sort" : [
2.2327789688700266
]
}
]
}
}
}
},
{
"key" : 1099,
"doc_count" : 8,
"reverse_merchant" : {
"doc_count" : 8,
"hits" : {
"hits" : {
"total" : {
"value" : 8,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "merchants-ops-qa",
"_type" : "_doc",
"_id" : "129",
"_score" : null,
"_source" : {
"merchant" : {
"id" : 1099
},
"id" : 129,
"title" : "Pizza Crush"
},
"sort" : [
2.390191854578742
]
}
]
}
}
}
},
{
"key" : 1139,
"doc_count" : 8,
"reverse_merchant" : {
"doc_count" : 8,
"hits" : {
"hits" : {
"total" : {
"value" : 8,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "merchants-ops-qa",
"_type" : "_doc",
"_id" : "296",
"_score" : null,
"_source" : {
"merchant" : {
"id" : 1139
},
"id" : 296,
"title" : "California Pizza"
},
"sort" : [
0.13160707636758653
]
}
]
}
}
}
}
]
}
}
}
}
In result you can see sorting is not working in sort field. Please help to achieve my goal. Thanaks.
I want to get the counts of(SUSPECT and CLEAR) Each State in API using Elastic Search query-
Data inside Elastic Search looks like-
Sample data-
{
"_index" : "index_name"
"_type" : "_doc",
"_id" : "id1",
"_score" : 1.0,
"_source" : {
"slflag" : "SUSPECT",
"state_name" : "UTTAR PRADESH",
}
{
"_index" : "index_name",
"_type" : "_doc",
"_id" : id2",
"_score" : 1.0,
"_source" : {
"slflag" : "CLEAR",
"state_name" : "UTTAR PRADESH",
}
{
"_index" : "index_name"
"_type" : "_doc",
"_id" : "id3",
"_score" : 1.0,
"_source" : {
"slflag" : "SUSPECT",
"state_name" : "Delhi",
}
{
"_index" : "index_name",
"_type" : "_doc",
"_id" : id4",
"_score" : 1.0,
"_source" : {
"slflag" : "CLEAR",
"state_name" : "Madhya Pradesh",
}
{
"_index" : "index_name"
"_type" : "_doc",
"_id" : "id5",
"_score" : 1.0,
"_source" : {
"slflag" : "SUSPECT",
"state_name" : "Rajasthan",
}
{
"_index" : "index_name",
"_type" : "_doc",
"_id" : id6",
"_score" : 1.0,
"_source" : {
"slflag" : "CLEAR",
"state_name" : "Bihar",
}
Fields are - state_name, slflag
In slflag field we have two categories - "SUSPECT" and "CLEAR"
I want to make a query to get such results-
{
"stateName": "UTTAR PRADESH",
"clear": 688,
"suspect": 182
},
{
"stateName": "Bihar",
"clear": 398456,
"suspect": 117110
},
{
"stateName": "Rajasthan",
"clear": 688,
"suspect": 182
},
{
"stateName": "Delhi",
"clear": 12096,
"suspect": 984
}
I don't know how to count slflag for each state.
Thanks in advance.
Get /index-
{
"index" : {
"aliases" : { },
"mappings" : {
"properties" : {
"#timestamp" : {
"type" : "date"
},
"#version" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"slflag" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"state_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"wl_d_ind" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1587554261571",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "zFKQmxyTSsyoVLRoCC_3IA",
"version" : {
"created" : "7060199"
},
"provided_name" : "index"
}
}
}
}
I tried below-
GET /index/_search
{
"size": 0,
"aggs": {
"states": {
"terms": {
"field": "state_name.keyword",
"size": 100
},
"aggs": {
"flag": {
"terms": {
"field": "slflag.keyword"
}
}
}
}
}
}
Above results in-
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"states" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "UTTAR PRADESH",
"doc_count" : 5403369,
"flag" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "CLEAR",
"doc_count" : 4540278
},
{
"key" : "SUSPECT",
"doc_count" : 863091
}
]
}
},
{
"key" : "RAJASTHAN",
"doc_count" : 2239768,
"flag" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "CLEAR",
"doc_count" : 1866196
},
{
"key" : "SUSPECT",
"doc_count" : 373572
}
]
}
},
{
"key" : "GOA",
"doc_count" : 12,
"flag" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "CLEAR",
"doc_count" : 12
}
]
}
}
]
}
}
}
You need to first aggregate on stateName and then on slflag, like this:
GET index_name/_search?filter_path=**.key,**.doc_count
{
"size": 0,
"aggs": {
"states": {
"terms": {
"field": "state_name.keyword",
"size": 100
},
"aggs": {
"flag": {
"terms": {
"field": "slflag.keyword"
}
}
}
}
}
}
I'm new to elasticsearch and struggling this situation (for example):
I want to index offices and clerks of each office. So, I've created this mapping:
PUT office
{
"mappings": {
"properties": {
"office_name": {
"type": "text"
},
"clerks": {
"type": "nested"
}
}
}
}
and indexing some data:
PUT /office/_doc/1
{
"name": "office a",
"clerks": [
{
"name": "a a a a"
},
{
"name": "a a"
},
{
"name": "b"
}
]
}
PUT /office/_doc/2
{
"name": "office b",
"clerks": [
{
"name": "a a a"
}
]
}
Now, I want to search for 'a':
GET /office/_search
{
"query": {
"nested": {
"path": "clerks",
"query": {
"match": {
"clerks.name": "a"
}
},
"inner_hits": {}
}
}
}
the result is:
{
"took" : 624,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.1272885,
"hits" : [
{
"_index" : "office",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.1272885,
"_source" : {
"name" : "office b",
"clerks" : [
{
"name" : "a a a"
}
]
},
"inner_hits" : {
"clerks" : {
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.1272885,
"hits" : [
{
"_index" : "office",
"_type" : "_doc",
"_id" : "2",
"_nested" : {
"field" : "clerks",
"offset" : 0
},
"_score" : 1.1272885,
"_source" : {
"name" : "a a a"
}
}
]
}
}
}
},
{
"_index" : "office",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.1184678,
"_source" : {
"name" : "office a",
"clerks" : [
{
"name" : "a a a a"
},
{
"name" : "a a"
},
{
"name" : "b"
}
]
},
"inner_hits" : {
"clerks" : {
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.1468691,
"hits" : [
{
"_index" : "office",
"_type" : "_doc",
"_id" : "1",
"_nested" : {
"field" : "clerks",
"offset" : 0
},
"_score" : 1.1468691,
"_source" : {
"name" : "a a a a"
}
},
{
"_index" : "office",
"_type" : "_doc",
"_id" : "1",
"_nested" : {
"field" : "clerks",
"offset" : 1
},
"_score" : 1.0900666,
"_source" : {
"name" : "a a"
}
}
]
}
}
}
}
]
}
}
I expect 'a a a' appears before 'a a' and the result to be like this:
[
{
"name": "a a a a"
},
{
"name": "a a a"
},
{
"name": "a a"
}
]
How can I achieve this result?
I have the following data in an Elasticsearch index called products
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "products",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"prod_id" : 1,
"currency" : "USD",
"price" : 1
}
},
{
"_index" : "products",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"prod_id" : 2,
"currency" : "INR",
"price" : 60
}
},
{
"_index" : "products",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"prod_id" : 3,
"currency" : "EUR",
"price" : 2
}
},
{
"_index" : "products",
"_type" : "_doc",
"_id" : "5",
"_score" : 1.0,
"_source" : {
"prod_id" : 5,
"currency" : "MYR",
"price" : 1
}
}
]
}
}
I am sorting the data based on the price field,
I have the following script to do so -
GET products/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [{
"script_score": {
"script": {
"params": {
"USD": 1,
"SGD": 0.72,
"MYR": 0.24,
"INR": 0.014,
"EUR": 1.12
},
"source": "doc['price'].value * (doc.currency.value == 'eur'? params.EUR : doc.currency.value == 'myr' ? params.MYR : doc.currency.value == 'inr' ? params.INR : 1)"
}
}
}]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
]
}
Because the field currency in the product index is of type text,
it is indexed with Standard Analyzer, which converts it to lower case.
I wish to optimise this part of the script, As I may end up with 20-30 currencies -
"source": "doc['price'].value * (doc.currency.value == 'eur'? params.EUR : doc.currency.value == 'myr' ? params.MYR : doc.currency.value == 'inr' ? params.INR : 1)"
I was able to optimize the source script with the following working solution -
GET products/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [{
"script_score": {
"script": {
"params": {
"USD": 1,
"SGD": 0.72,
"MYR": 0.24,
"INR": 0.014,
"EUR": 1.12
},
"source": "doc['price'].value * params[doc['currency.keyword'].value]"
}
}
}]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
]
}