Dynamic elasticsearch queries - php

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

Related

Elastisearch Failed to JSON encode issue

I working on elastic search and I have 1K phone numbers when I pass this phone numbers array to elastic search to search users through phone numbers it gives me exception
Failed to JSON encode /var/app/current/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Serializers/SmartSerializer.php
Below is my Elasticsearch client initializing
$client = ClientBuilder::create()->setHosts([$host])->build();
And my working query in Elasticsearch
{
"_source": [
"id"
],
"query": {
"bool": {
"must": [
{
"term": {
"type": "user"
}
},
{
"bool": {
"should": [
{
"prefix": {
"phone": {
"value": "923047698099"
}
}
},
{
"prefix": {
"phone": {
"value": "92313730320"
}
}
},
.
.
.
]
}
}
],
"must_not": [
{
"has_child": {
"type": "blocked",
"query": {
"term": {
"user_id": "u-2"
}
}
}
},
{
"has_child": {
"type": "block",
"query": {
"term": {
"user_id": "u-2"
}
}
}
},
{
"term": {
"db_id": 2
}
}
]
}
}
}
I don't know that where I doing mistake. Either at client initializing or writing elasticserch query. I searched this issue but not usefull solution found or might be I did't understand clearly. But still I am stucked on this issue that how to solve this problem. Suggest any usefull link or solution.
Thanks

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"
}
}
}
]
}
}
}

Elastic Search different reults on URL query and JSON POST

I'm completing a search function on a big online webstore.
I have a problem with additional fields. When I try searching for some fields in browser, it works, but when posting a JSON using bool filter, it gives me 0 results (doesn't raise an error).
Basically: when I visit localhost:9200/search/items/_search?pretty=true&q=field-7:Diesel
It works well, however, in JSON it doesn't.
I've been googling all day and couldn't find any help in ElasticSeach documents. What frustrates me even more is that some other fields in bool query work OK, but this one doesn't.
I don't have any mapping and ES works for me out of the box - querying on the "name" field works well, as well as any other field, as well as for this field too - but only inside browser.
I realise that querying ES over browser uses so called "query string query".
Anyway, here is an example JSON that I'm posting to ElasticSearch.
(searching all items that have "golf mk5" in their name, which have diesel fuel type - by searching field-7).
{
"query": {
"filtered": {
"filter": {
"bool": {
"must_not": [
{
"term": {
"sold": "1"
}
},
{
"term": {
"user_id": "0"
}
}
],
"must": [
{
"term": {
"locked": "0"
}
},
{
"term": {
"removed": "0"
}
},
{
"terms": {
"field-7": [
"Diesel"
]
}
}
]
}
},
"query": {
"match": {
"name": {
"operator": "and",
"query": "+golf +Mk5"
}
}
}
}
},
"sort": [
{
"ordering": {
"price": "desc"
}
}
],
"from": 0,
"size": 24,
"facets": {
"category_count": {
"terms": {
"field": "category_id",
"size": 20,
"order": "count"
}
},
"price": {
"statistical": {
"field": "price"
}
}
}
}
Using a query_string-query, the text is analyzed. With the term-query (and -filter), it is not.
Since you're not specifying a mapping, you'll get the standard-analyzer for string fields. It tokenizes, lowercases and removes stopwords.
Thus, the term Diesel will be indexed as diesel. Your terms-filter is looking up the exact term Diesel, which is different.

_score while doing indexing in elasticsearch

{
"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.

Categories