ElasticSearch Custom Script for Ordering Performance - groovy

I wrote a simple scoring based on a document parameter like below:
POST /_scripts/groovy/CustomScoring
{
"script": "(_source.ProductHits==null ? 0.1 :
(_source.ProductHits[myval]==null?0.2:_source.ProductHits[myval]))"
}
When I use this custom script to sort search results like this:
POST /ecs/product/_search
{
"query": {
"bool": {
"must": [
{
"function_score":{
"query" : {"match_all": {}}
,"script_score": {
"script_id": "CustomScoring",
"lang" : "groovy",
"params":{
"myval": "iphone"
}
}
}
}
]
}
}
}
It takes 800ms to run on 50'000 documents (vs initial run-time which was around 1ms).
How can I optimize this groovy function?
Can Elasticsearch use some kind of caching for this function?
p.s. When I tried to use sum complex formulas based on doc.some_param.value and embedded functions like log it took 40ms instead which is still reasonable.

Related

Facing difficulty using compound query with Elasticsearch JS

I am using the official Elasticsearch package from npm within my node.js application. I was attempting to perform search using compound queries ( bool), But I found that the compound search does not work as expected.
To debug the issue, I tried passing different sets of data for the search query. I found an abnormality wherein the elasticsearch library does not work as expected but the Elasticsearch API does. I'm unable to find this behavior documented anywhere else as well.
I executed 2 sets of code (with the same query) on
1) Node using the official elastic search library
2) Over the Elasticsearch API using Postman
I> Using Elastic Search JS
"index": "bank",
"type": "account",
"body": {
"query": {
"bool": {
"must": [{
"match": {
"address": "avenue"
}
}]
}
}
}
}
II> Using Elastic Search API
"query": {
"bool": {
"must": [{
"match": {
"address": "avenue"
}
}]
}
}
}
The results for the official library come in empty (Empty array), But the results using the elasticsearch API result in the correct set of data.
Another peculiar observation was the below query using elasticsearch JS which works for a single element, but not an array of elements
"index": "bank",
"type": "account",
"body": {
"query": {
"bool": {
"must": {
"match": {
"address": "avenue"
}
}
}
}
}
}
I'm breaking my head over where I'm going wrong, I tried going through docs, stackoverflow and a very little bit of code, And returned empty handed.
Would appreciate any help.
Thanks a lot

ElasticSearch search with querystring and verify another field

I need to translate the following SQL query to ES query:
SELECT *
FROM SKILL
WHERE SKILL.name LIKE 'text' and SKILL.type = 'hard'
I have tried the following using "elasticsearch" library for python3:
query = self.__es.search(index="skills",
body={"from" : skip, "size" : limit,
"query":
{"query_string":
{"query": 'text'}
})
and this worked well. But now, I don't know how to check that the field 'type' is equal to 'hard'.
How can I do that?
Thank you.
You have to use a bool query and in the "must" part put two queries, the full text one and a term one:
{
"query": {
"bool": [{
"match": {
"name": "this is a test"
}
}, {
"term": {
"type": "hard"
}
}]
}
}
Before this you have to store the type property as a keyword field.

How would I query keys such that it would partially match?

Let's take this document for example:
{
"id":1
"planet":"earth-616"
"data":[
["wolverine","mutant"],
["Storm","mutant"],
["Mark Zuckerberg","human"]]
}
I created a search index to index the name and type, for example if searched for name:wolverine or type:mutant I'd get the document that has it. But as per my requirement I don't want the whole document, I only want ["wolverine","mutant"] I've created a view that outputs as:
{
"id":1,
"key":"earth-616",
"value":["earth-616","wolverine","mutant"]
}
Then I found out I can query only with keys. (Is it possible to create search indexes on views?, Couldn't find anything in the documentation)
Or should I create views along with the one above like this:
{
"id":1,
"key":"wolverine",
"value":["earth-616","wolverine","mutant"]
}
And
{
"id":,
"key":"mutant"
"value":["earth-616","wolverine","mutant"]
}
This way I can query with keys that I want but I can't seem to partial match keys(Am I missing something?)
If you need the output to be exactly as described then I believe you have to use views, and to support wildcard searches I believe you will have to index every substring of a key.
One alternative is to use Cloudant Query, although admittedly you cannot get the exact output you are looking for. If you issue a query like so:
{
"selector": {
"_id": {
"$gt": 0
},
"data": {
"$elemMatch": {
"$elemMatch": {
"$regex": "(?i)zuck"
}
}
}
},
"fields": [
"data"
]
}
The result will be the entire data array:
{
"data": [
["wolverine", "mutant"],
["Storm", "mutant"],
["Mark Zuckerberg", "human"]
]
}

Query the number of elements matching a filter using elastic.js?

I'm building a leaderboard with elasticsearch. I'd like to query all documents who have points greater than a given amount using the following query:
{
"constant_score" : {
"filter" : {
"range" : {
"totalPoints" : {
"gt": 242
}
}
}
}
This works perfectly -- elasticsearch appropriately returns all documents with points greater than 242. However, all I really need is the count of elements matching this query. Since I'm sending the result over the network, it would be helpful if the query simply returned the count, as opposed to all of the documents matching the filter.
How do I get elasticsearch to only report the count of documents matching the filter?
EDIT: I've learned that what I'm looking for is setting search_type to count. However, I'm not sure how to do this with elastic.js. Any noders willing to pitch in their advice?
You can use the query type count for exactly that purpose:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#count
This is an example that should help you:
GET /mymusic/itunes/_search?search_type=count
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"range": {
"year": {
"gt": 2000
}
}
}
}
}
}

Elasticsearch: how to get matching types list?

My elasticsearch index has 10 types in it. When searching for the term "test" I want to get all the documents that matched that query and a list of all the types that has a least one match for that query.
I know I can get this list by going over all results but I guess there's a better way..
Thanks!
Since facets have been deprecated (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-facets.html) and replaced with aggregations, here is the solution for aggregations:
{
"query": {
...
},
"aggs": {
"your_aggregation_name": {
"terms": {
"field": "_type"
}
}
}
}
Link to documentation: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
Just managed to do that with elasticsearch facets like described here:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html#_facet_filter
In short you add this to your query:
"facets" : { "facet_name" : { "terms" : {"field" : "_type"} } }
Hope this help someone.

Resources