Elasticsearch - MissingMethodException on running distanceInKm on geo_point array - groovy

I have an elasticsearch document which has an array of geo_points. I have created the mapping as:
{
"test": {
"properties": {
"locations": {
"type": "geo_point"
}
}
}
}
Now, I am trying to create a query in which I want to do some processing on the array of geo_points. I have created my query like this:
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "sDistance = doc['locations'].values[0].distanceInKm(28.51818,77.096080);"
}
}
}
}
}
I want to calculate the distance of the point (28.51818,77.096080) from the first element in the locations array.
It is giving me this error:
GroovyScriptExecutionException[MissingMethodException[No signature of method: org.elasticsearch.common.geo.GeoPoint.distanceInKm() is applicable for argument types: (java.lang.Double, java.lang.Double) values: [28.51818, 77.09608]]
I tried using sDistance = doc['locations'][0].distanceInKm(28.51818,77.096080); but it also resulted in the same error.
What am I doing wrong here?
Thanks in advance.

Your script should not retrieve the first geo point by itself, but simply call distanceInKm on the locations field directly, like this:
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "sDistance = doc['locations'].distanceInKm(28.51818,77.096080);"
}
}
}
}
}
Under the hood, the first geo point will be retrieved and the distance will be computed on it.

Related

How can I sort price string in ElasticSearch?

In my example i tried to sort but i have no success. My problem is because my price is string and the price is like that => 1.300,00. When I sort string price i have that for exemplo. 0,00 | 1,00 | 1.000,00 | 2,00.
I wanna format format in double for sort or like similar that.
How can i do that ?
It is not a good idea to keep Price as a keyword in Elastic search best approach would be to map price as scaled float in elastic search like this:
New Mapping:
PUT [index_name]/_mapping
{
"properties": {
"price2": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
To solve your problem you can add new mapping and convert your value from string to numeric value:
Update by query:
POST [index_name]/_update_by_query
{
"query": {
"match_all": {}
},
"script": {
"source": "ctx._source['price2'] = ctx._source['price'].replace(',','')"
}
}
This query will convert your keyword value to string and map it in another field named price2, then you will need to have an ingest pipeline to do the process to new entries:
Ingest pipeline:
POST _ingest/pipeline/_simulate
{
"pipeline": {
"processors": [
{
"script": {
"description": "Extract 'tags' from 'env' field",
"lang": "painless",
"source": "ctx['price2'] = ctx['price'].replace(',','')"
}
}
]
},
"docs": [
{
"_source": {
"price": "5,000.00"
}
}
]
}
You need to remove _simulate and add this ingest pipeline to your index.

Considering multiple fields when searching in Elasticsearch

I want to implement a simple search query using Elasticsearch.
I have two fields, "title" and "description" that I would like to match the searched term with. Currently, I have the body shown below as the body for search body. How can I make it so that the search prioritizes the title match, but if there are matches in the description, they are still included in the search (with lower priority)? Thanks in advance.
body = {
size: 200,
from: 0,
query: {
prefix: {
title: searchTerm
}
}
}
You have to use a constant score query with a score of 0 for the "other" field. Any other boost / function score usage will not reliably score a certain field over another field as the scoring is based on other parameters like text length for example, this means a constant boost (unless very very large) can not guarantee the behaviour you seek.
By using a constant score for each field you can control score manually, like so:
{
size: 200,
from: 0,
query: {
bool: {
should: [
{
prefix: {
title: searchTerm
}
},
{
constant_score: {
filter: {
prefix: {
description: searchTerm
}
},
boost: 0
}
},
]
}
}
}
If you set description boost to be more than 0 then the score will be the combined score of both fields, by doing this you can prioritize documents that have that prefix in both fields over ones that have it in just the title field.
You can use a combination of bool/should clause along with the boost parameter
{
"query": {
"bool": {
"should": [
{
"prefix": {
"title": {
"value": "searchterm"
}
}
},
{
"prefix": {
"description": {
"value": "searchterm",
"boost": 4
}
}
}
]
}
}
}

Couchdb 2 _find query not using index

I'm struggling with something that should be easy but it's making no sense to me, I have these 2 documents in a database:
{ "name": "foo", "type": "typeA" },
{ "name": "bar", "type": "typeB" }
And I'm posting this to _find:
{
"selector": {
"type": "typeA"
},
"sort": ["name"]
}
Which works as expected but I get a warning that there's no matching index, so I've tried posting various combinations of the following to _index which makes no difference:
{
"index": {
"fields": ["type"]
}
}
{
"index": {
"fields": ["name"]
}
}
{
"index": {
"fields": ["name", "type"]
}
}
If I remove the sort by name and only index the type it works fine except it's not sorted, is this a limitation with couchdbs' mango implementation or am I missing something?
Using a view and map function works fine but I'm curious what mango is/isn't doing here.
With just the type index, I think it will normally be almost as efficient unless you have many documents of each type (as it has to do the sorting stage in memory.)
But since fields are ordered, it would be necessary to do:
{
"index": {
"fields": ["type", "name"]
}
}
to have a contiguous slice of this index for each type that is already ordered by name. But the query planner may not determine that this index applies.
As an example, the current pouchdb-find (which should be similar) needs the more complicated but equivalent query:
{
selector: {type: 'typeA', name: {$gte: null} },
sort: ['type','name']
}
to choose this index and build a plan that doesn't resort to building in memory for any step.

Elasticsearch Nest Query not returning result as expected

I'm new to Elasticsearch. I'm trying a query and when giving full name I'm getting results. When I give part of it, it's not returning any results. Below is the sample that I have been trying.
{
"query": {
"multi_match": {
"query": "recharge",
"fields": ["category.*","categoryName^3","alterNames","categoryDescription"],
"type": "best_fields"
}
},size:1000
}
If I pass "rech" in the query, I'm not getting any results. Can any one help me here?
As far as I understand, you want to get the results with unfinished query, so you need a wildcard, like this:
{
"query": {
"multi_match": {
"query": "rech*",
"fields": ["category.*", "categoryName^3", "alterNames", "categoryDescription"],
"type": "best_fields"
}
}

Elasticsearch term filter on inner object field not matching

I have just organized my document structure to have a more OO design (e.g. moved top level properties like venueId and venueName into a venue object with id and name fields).
However I can now not get a simple term filter working for fields on the child venue inner object.
Here is my mapping:
{
"deal": {
"properties": {
"textId": {"type":"string","name":"textId","index":"no"},
"displayId": {"type":"string","name":"displayId","index":"no"},
"active": {"name":"active","type":"boolean","index":"not_analyzed"},
"venue": {
"type":"object",
"path":"full",
"properties": {
"textId": {"type":"string","name":"textId","index":"not_analyzed"},
"regionId": {"type":"string","name":"regionId","index":"not_analyzed"},
"displayId": {"type":"string","name":"displayId","index":"not_analyzed"},
"name": {"type":"string","name":"name"},
"address": {"type":"string","name":"address"},
"area": {
"type":"multi_field",
"fields": {
"area": {"type":"string","index":"not_analyzed"},
"area_search": {"type":"string","index":"analyzed"}}},
"location": {"type":"geo_point","lat_lon":true}}},
"tags": {
"type":"multi_field",
"fields": {
"tags":{"type":"string","index":"not_analyzed"},
"tags_search":{"type":"string","index":"analyzed"}}},
"days": {
"type":"multi_field",
"fields": {
"days":{"type":"string","index":"not_analyzed"},
"days_search":{"type":"string","index":"analyzed"}}},
"value": {"type":"string","name":"value"},
"title": {"type":"string","name":"title"},
"subtitle": {"type":"string","name":"subtitle"},
"description": {"type":"string","name":"description"},
"time": {"type":"string","name":"time"},
"link": {"type":"string","name":"link","index":"no"},
"previewImage": {"type":"string","name":"previewImage","index":"no"},
"detailImage": {"type":"string","name":"detailImage","index":"no"}}}
}
Here is an example document:
GET /production/deals/wa-au-some-venue-weekends-some-deal
{
"_index":"some-index-v1",
"_type":"deals",
"_id":"wa-au-some-venue-weekends-some-deal",
"_version":1,
"exists":true,
"_source" : {
"id":"921d5fe0-8867-4d5c-81b4-7c1caf11325f",
"textId":"wa-au-some-venue-weekends-some-deal",
"displayId":"some-venue-weekends-some-deal",
"active":true,
"venue":{
"id":"46a7cb64-395c-4bc4-814a-a7735591f9de",
"textId":"wa-au-some-venue",
"regionId":"wa-au",
"displayId":"some-venue",
"name":"Some Venue",
"address":"sdgfdg",
"area":"Swan Valley & Surrounds"},
"tags":["Lunch"],
"days":["Saturday","Sunday"],
"value":"$1",
"title":"Some Deal",
"subtitle":"",
"description":"",
"time":"5pm - Late"
}
}
And here is an 'explain' test on that same document:
POST /production/deals/wa-au-some-venue-weekends-some-deal/_explain
{
"query": {
"filtered": {
"filter": {
"term": {
"venue.regionId": "wa-au"
}
}
}
}
}
{
"ok":true,
"_index":"some-index-v1",
"_type":"deals",
"_id":"wa-au-some-venue-weekends-some-deal",
"matched":false,
"explanation":{
"value":0.0,
"description":"ConstantScore(cache(venue.regionId:wa-au)) doesn't match id 0"
}
}
Is there any way to get more useful debugging info?
Is there something wrong with the explain result description? Simply saying "doesn't match id 0" does not really make sense to me... the field is called 'regionId' (not 'id') and the value is definitely not 0...???
That happens because the type you submitted the mapping for is called deal, while the type you indexed the document in is called deals.
If you look at the mapping for your type deals, you'll see that was automatically generated and the field venue.regionId is analyzed, thus you most likely have two tokens in your index: wa and au. Only searching for those tokens on that type you would get back that document.
Anything else looks just great! Only a small character is wrong ;)

Resources