_score while doing indexing in elasticsearch - php

{
"query": {
"custom_score": {
"query": {
"match": {
"xxx": {
"query": "foobar"
}
}
},
"filter": {
"and": [
{
"query": {
"match": {
"yyyy": {
"query": "barfoo"
}
}
}
}
]
}
},
"script": "_score * doc['_score']"
}
}
This gives error
[custom_score] query does not support [filter]
Then how to evaluate such query?

I would suggest you to look at your requirements regarding boosting, since your current script doesn't make much sense.
Also, have a look at the documentation for the elasticsearch query DSL. It provides either compound queries and simple ones, which you can combine together. As the error says, you can't put a filter inside a custom score query. You can either use a filtered query inside the custom score query:
{
"query": {
"custom_score": {
"query": {
"filtered" : {
"query" : {
"match": {
"xxx": {
"query": "foobar"
}
}
},
"filter" : {
"and": [
{
"query": {
"match": {
"yyyy": {
"query": "barfoo"
}
}
}
}
]
}
}
},
"script": "_score * doc['_score']"
}
}
}
or use a top level filter like this:
{
"query": {
"custom_score": {
"query": {
"match": {
"xxx": {
"query": "foobar"
}
}
},
"script": "_score * doc['_score']"
}
},
"filter": {
"and": [
{
"query": {
"match": {
"yyyy": {
"query": "barfoo"
}
}
}
}
]
}
}
The difference between the two options is that the top level filter is not considered if you make facets too in your search request, while if you put the filters within the query they are considered.
One other thing to look at: you don't need an and filter if you have only a single clause. Also, it usually doesn't make sense to put a full-text search within a filter, since filters are cacheable and given that full-text searches are free and pretty much unpredictable it would be a waste to cache them.

Related

Convert an infix expression to elastic search query

How can I convert an infix expression to an elastic search query
my operators are ! + *
and user may make any expression using those operators, something like:
(((A*B*(!C))*(D*E))+F)*G
and I wish to convert it to a bool query in elastic search
Edit
I don't know why I didn't say this earlier but I have already written a code to convert infix to postfix expression and then I call a very dirty recursive method to create should (+), must (*) and must_not (!) but what i'm seeking is an optimized way to do the trick for me.
My query at the end is something like this which I think is very very nasty:
{
"from": 0,
"size": 10,
"_source": [
"*"
],
"index": "insta_userpost_new2",
"body": {
"query": {
"bool": {
"must": [
{
"match_phrase": {
"caption.text": "G"
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"caption.text": "F"
}
},
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"match_phrase": {
"caption.text": "E"
}
},
{
"match_phrase": {
"caption.text": "D"
}
}
]
}
},
{
"bool": {
"must": [
{
"bool": {
"must_not": [
{
"match_phrase": {
"caption.text": "C"
}
},
{
"bool": {
"must": [
{
"match_phrase": {
"caption.text": "B"
}
},
{
"match_phrase": {
"caption.text": "A"
}
}
]
}
}
]
}
}
]
}
}
]
}
}
]
}
}
]
}
}
}
}
I would maybe try to leverage simply_query_string. For that, you'd have to:
replace + by | (for the OR)
then replace * by + (for the AND)
finally replace ! by - (for the NOT)
So if a user inputs this:
(((A*B*(!C))*(D*E))+F)*G
You'd end up with this
(((A+B+(-C))+(D+E))|F)+G
Which is a boolean expression that you can directly use in a simply_query_string query.
GET /_search
{
"query": {
"simple_query_string" : {
"fields" : ["content"],
"query" : "(((A+B+(-C))+(D+E))|F)+G"
}
}
}
You can use Elasticsearch scripts in queries, like this:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-query.html
There are few scripting options, with the most simple and strait forward is 'Painless' scripts. From elastic documentation:
When you define a scripted field in Kibana, you have a choice of scripting languages. Starting with 5.0, the default options are Lucene expressions and Painless
Also you can return the result of the calculation using Scripted Fields:
https://www.elastic.co/guide/en/kibana/current/scripted-fields.html
You can run an infix expression evaluation[1] and replace the standard eval operations with DSL bool query composers.
We actually do something akin to this for https://opensource.appbase.io/mirage/ (you can try it live), where we map GUI blocks to a composable bool query. The source code is viewable at https://github.com/appbaseio/mirage.
[1] Ref: https://www.geeksforgeeks.org/expression-evaluation/

How to group a query to match one or more words in elasticsearch?

I have this query
{
"bool": {
"should": [
{
"multi_match": {
"query": "LAS VEGAS, HENDERSON",
"fields": ["city"]
}
}
]
}
}
this returns:
"city": "LAS VEGAS",
"city": "LAS CRUCES",
"city": "HENDERSON",
Note the LAS CRUCES result. I don't want it.
One way would be to have it written like this:
"bool": {
"should": [
{
"match": {
"city": {
"query": "LAS VEGAS",
"operator": "and"
}
}
},
{
"match": {
"city": {
"query": "HENDERSON",
"operator": "and"
}
}
}
}
But I prefer the first approach, if it can be done.
Any ideas?
You can use query_string query as shown below:
GET /_search
{
"query": {
"query_string" : {
"fields" : ["city"],
"query" : "\"LAS VEGAS\" OR \"HENDERSON\""
}
}
}
You need to enclose the values in quotes to search for exact phrase.
If you are using city field for searching exact matches then you should consider changing it's mapping type from text to keyword. It will fetch you good performance.
If your city field is of type keyword then you can achieve the same results using terms query as shown below:
GET /_search
{
"query": {
"constant_score" : {
"filter" : {
"terms" : { "city" : ["LAS VEGAS", "HENDERSON"]}
}
}
}
}
Hope this helps!
multi_match accepts the operator flag, which can be set to or.
{
"bool": {
"should": [
{
"multi_match": {
"query": "LAS VEGAS, HENDERSON",
"fields": ["city"],
"operator": "or"
}
}
]
}
}

Multi indices search with nested fields

I have two indices:
First, questions, have nested field answers. Second, articles do not have this field.
I try search by multi indices:
{
"index": "questions, articles",
"body":{
"query":{
"bool":{
"must":{
"nested":{
"path": "answer",
...
}
}
}
}
}
}
and get error "query_parsing_exception: [nested] failed to find nested object under path [answer]"
How I can search without errors, when one index have nested field, but another does not have?
I think you need to use the indices query and to use a different query for each index. Something like this:
GET /questions,articles/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"indices": {
"indices": [
"questions"
],
"query": {
"nested": {
"path": "answer",
"query": {
"term": {
"text": "bla"
}
}
}
}
}
},
{
"match_all": {}
}
]
}
},
{
"term": {
"some_common_field": {
"value": "whatever"
}
}
}
]
}
}
}

How to do Tagging and excluding Filters in ElasticSearch?

Like When filter is set for faceted/aggregated filter it should be excluded, so we won't get just one result.
If user selects some brand ,the result should come with only the selected brand ,but the aggregation should return all the brand filters that were already there, so that user can select other brands also.
How can we do it in Elasticsearch? Same can be accessed in solr using Tagging and excluding Filters
Use a post_filter to filter the search results but still show all data in the aggregation.
See Post Filter:
The post_filter is applied to the search hits at the very end of a
search request, after aggregations have already been calculated. It’s
purpose is best explained by example:
curl -XGET localhost:9200/shirts/_search -d '
{
"query": {
"filtered": {
"filter": {
{ "term": { "brand": "gucci" }}
}
}
},
"aggs": {
"colors": {
"terms": { "field": "color" },
},
"color_red": {
"filter": {
"term": { "color": "red" }
},
"aggs": {
"models": {
"terms": { "field": "model" }
}
}
}
},
"post_filter": {
"term": { "color": "red" },
}
}
'

Dynamic elasticsearch queries

I've just started using elasticsearch and I'm unsure how you go about using dynamic search queries. Currently I am using something like this:
$params['body'] = '
{
"query": {
"multi_match": {
"query": "' . $terms . '",
"fields": [
"title^1",
"description"
],
"minimum_should_match": "70%"
}
},
"highlight": {
"pre_tags" : ["<b>"],
"post_tags" : ["</b>"],
"fields": {
"description": {
"fragment_size": 400
},
"title": {
"number_of_fragments": 0
}
}
}
}
}';
This works fine when $terms is just a string like ball. What I'm trying to do is be able for a user to search by string ball but maybe they want a ball from a particular location also and would have an optional location check box,if clicked a $state could be part of the query now. I looked into Bool Query
but I just wasn't sure if this was the right approach. Any guidance would be great.
Updated code
{
"query": {
"bool": {
"must": [
{
"term": {
"description": {
"value": "' . $terms .'"
}
}
},
{
"term": {
"state_id": {
"value": "' . $location . '"
}
}
}
]
}
}
}';
I'm just using a simple if(isset() in PHP to see if the terms are there and one for the location. If there is no location $_GET variable i'm just setting it as null.
The bool query is one of the best approach for querying more than one query.
curl -XPOST "http://192.168.31.16:9200/appviewx/ro/_search" -d'
{
"query": {
"bool": {
"must": [
{
"term": {
"object": {
"value": "ball"
}
}
},
{
"term": {
"location": {
"value": "state"
}
}
}
]
}
}
}'
Put these in if block
curl -XPOST. "http://192.168.31.16:9200/appviewx/ro/_search" -d'
{
"query": {
"bool": {
"must": [
{
"term": {
"object": {
"value": "ball"
}
}
}
]
}
}
}'
There are three types in bool.Must,Should,Must_not.
1)Should act as like OR condition
2)Must act as like AND condition
3)Must_not act as like NOT condition
Use filter as much as u can to increase performance. refer

Categories