I cannot figure out the following:
A database with address fields (country, county, city) and an "operate" field, options: locally, nationally internationally
I want to find matches based on location and the "operate" status. So I am basically searching for how to use MySQL OR in ElasticSearch. To my understanding this is "should".
So, any entry that operates internationally should be in the results, any entry that operates nationally in the same country and any entry that operates locally in the same county regardless which city is selected
Just as a test case, I tried several things among which the following:
$arrayinternationally[] = array('match' => array('operate' => 'internationally'));
$arrayNationally[] = array('match' => array('operate' => 'nationally'));
$arrayNationally[] = array('match' => array('country' => '60'));
$arrayLocally[] = array('match' => array('operate' => 'locally'));
$arrayLocally[] = array('match' => array('country' => 'UK'));
$arrayLocally[] = array('match' => array('county' => '60'));
$params = [
'index' => 'bzlistings',
'body' => [
'from' => 0,
'size' => 80,
'query' => [
'bool' => [
'should' => [
'bool' => [
'should' => $arrayinternationally
]
],
'should' => [
'bool' => [
'should' => $arrayNationally
]
],
'should' => [
'bool' => [
'should' => $arrayLocally
]
],
],
],
],
];
Those entries in another country with "operate" set to "internationally", are not included, which is wrong.
How can this be done in ElasticSearch?
Thanks,
Peter
I think there is something wrong with the bool queries. Could you test with following query :
$params = [
'index' => 'bzlistings',
'body' => [
'from' => 0,
'size' => 80,
'query' => [
'bool' => [
'should' => [
[
'bool' => [
'must' => $arrayinternationally
]
],
[
'bool' => [
'must' => $arrayNationally
]
],
[
'bool' => [
'must' => $arrayLocally
]
],
],
],
],
],
];
But I think, in your case, inner bools need to be must instead of should. Also, I recommend that if you are looking for exact matching, you can use term query instead of match.
Typically, the bool query structure is something like the below :
GET sample-index/_search
{
"query": {
"bool": {
"should": [
{},
{}
]
}
}
}
Related
Does anyone know a good resource with elasticsearch-php examples ideally covering queries taking MySQL Examples. I am struggling both with the code syntax and what to use when.
For example, I want to do a search where $name must be part of field 'business' and where 'country' matches $country
$params = [
'index' => 'xxxxx',
'type' => 'zzzzz',
'body' => [
'from' => 0,
'size' => $maxResults,
'query' => [
'bool' => [
'must' => [
'match' => ['name' => $searchString],
],
'must' => [
'match' => ['country' => $country],
],
],
],
],
];
The first 'must' seems to be completely ignored. Removing this will return exactly the same results.
I searched around for hours. There are plenty of quick beginner tutorials with simple search examples but I already get stuck one step further like with the above example
Thanks
You can only have a single must in a bool query, then all must constraints must be elements of the must array. Try like this instead:
$params = [
'index' => 'xxxxx',
'type' => 'zzzzz',
'body' => [
'from' => 0,
'size' => $maxResults,
'query' => [
'bool' => [
'must' => [
[
'match' => ['name' => $searchString],
],
[
'match' => ['country' => $country],
],
]
],
],
],
];
Trying to query in Elasticsearch w/ the PHP client and give priority to partial words matches but still include fuzzy matches. If I remove the address.company match block, the query works as expected, but is broken with it present no matter how I seem to frame it. I am lost on the formatting to also include the fuzzy searches with a lower priority?
$search_data = [
"from" => (int) $start, "size" => (int) $count,
'query' => [
'bool' => [
'filter' => [
['term' => ['active' => 1]],
['term' => ['type' => 2]],
],
'must' => [
'wildcard' => [
'address.company' => '*' . $search_query . '*'
],
'match' => [
'address.company' => [
'query' => $search_query,
'operator' => 'and',
'fuzziness' => 'AUTO',
],
],
],
],
],
];
While I am still new to ES as likely is apparent, this solution seems to get the data I'm after. I only mention that because there may be a more ideal way if someone views this in the future. Switching from must to should and wrapping the arrays a bit differently did the trick.
$search_data = [
"from" => (int) $start, "size" => (int) $count,
'query' => [
'bool' => [
'filter' => [
['term' => ['active' => 1]],
['term' => ['type' => 2]],
],
'should' => [
[
'match' => ['address.company' => ['query'=>$search_query,'boost'=>10]],
],
[
'match' =>
[
'address.company' =>
[
'query' => $search_query,
'fuzziness' => 'AUTO',
],
],
],
],
'minimum_should_match'=>1,
],
],
];
I want to create top search query using elasticsearch.
I want to match category_name, brand_name and title from elasticsearch table. The match should be phrase and with or condition.
My query:
$query = [
"bool" => [
"must" => [
["match" => ["is_published" => 1]],
[
"multi_match" => [
"query" => $searchKey,
"fields" => ["category_name", "brand_name", "title"]
]
],
[
'nested' => [
'path' => 'category_with_in_title.parent_cat',
'query' => [
'bool' => [
'must' => [
['match' => [
'category_with_in_title.parent_cat.status' => 1,
]],
],
],
],
],
],
[
'nested' => [
'path' => 'brand',
'query' => [
'bool' => [
'must' => [
'match' => [
'brand.approved_status' => 1,
],
],
],
],
],
],
[
'nested' => [
'path' => 'default_product_low_price_with_seller.seller_detail',
'query' => [
'bool' => [
'must' => [
'match' => [
'default_product_low_price_with_seller.seller_detail.approve_status' => 1,
],
],
],
],
],
],
[
'nested' => [
'path' => 'default_product_low_price_with_seller',
'query' => [
'bool' => [
'must' => [
'match' => [
'default_product_low_price_with_seller.status' => 1,
],
],
],
],
],
],
],
],
];
I use multi_match for that but how to use pharse in this query? I have to write whole word to search.
For example :
I want to search the record whose category_name = Tops
I want result if i write "tops" or "top" or "to". But right now I have to write "Tops" the exact word.
Thanks in advance...
You could use match_phrase_prefix, which is the same as match_phrase, except that it allows for prefix matches on the last term in the text.
All that you need to do, is add "type": "phrase_prefix" to your multi_match query, like this:
"multi_match" => [
"query" => $searchKey,
"type": "phrase_prefix",
"fields" => ["category_name", "brand_name", "title"]
]
Let me know if this is what you're looking for.
Ideally you should use multi_match with cross_fields type, which will treat all fields as ONE big field and run your query on it. However, due to fuzziness being disabled on these, only the exact match will show.
See Revelant Github Issue https://github.com/elastic/elasticsearch/issues/6866
Hence, my recommendation is to replace multi_match with fuzzy_like_this (elasticsearch version 1.x) or more_like_this (elasticsearch version 2.x).
$query = [
"bool" => [
"must" => [
["match" => ["is_published" => 1]],
[
"fuzzy_like_this" => [
"fields" => ["category_name", "brand_name", "title"],
"like_text" => $searchKey
]
],
....
I'm using Elastic search in Laravel.
So I have query that returns correct result:
$results = Es::search(array(
'index' => 'testindex',
'type' => $type,
'body' => [
'query' => [
'filtered' => [
'query' => [
'match' => [
'_all' => '2015-02'
]
],
'filter' => [
'bool' => [
'must' => [
'term' => [
'type' => 11
]
],
]
]
]
],
'size' => 5,
'from' => 0
]
));
What it does is:
searches for $query in all fields AND
field "type" must be 11.
Here is output: http://pastebin.com/icWniix4
Total 9 results which is correct.
But when I add another must term then it returns invalid results
$results = Es::search(array(
'index' => 'testindex',
'type' => $type,
'body' => [
'query' => [
'filtered' => [
'query' => [
'match' => [
'_all' => '2015-02'
]
],
'filter' => [
'bool' => [
'must' => [
'term' => [
'type' => 11
],
'term' => [
'public' => 1
]
],
]
]
]
],
'size' => 5,
'from' => 0
]
));
So this only add term for "public".
What it does is:
searches for $query in all fields AND
field "type" must be 11 AND
field "public" must be 1
So now results are in total 429. It ignores "type" term and returns everything with "public" = 1. But as per docs if I use MUST then it should match all of them. Search result http://pastebin.com/cVcatcyi
So how can I write query that I need? $query + type + public
Official doc's fail to answer my questions.
Any advice?
This is your trouble spot:
'must' => [
'term' => [
'type' => 11
],
'term' => [
'public' => 1
]
]
Here, you're assigning the value of must as an associative array that has only one distinct key - term actually gets assigned twice, so presumably only one of the assignments will "survive" (presumably public survives because it appears last in the definition). The end result is that must ends up pointing at an associative array with only one key-value pair.
What I suspect you have to do is this:
'must' => [
[
'term' => [
'type' => 11
]
],
[
'term' => [
'public' => 1
]
]
]
Now must is actually pointing at an array with two items.
I am using ES for my Laravel app.
What I want to do is a search filtering.
I do a fulltext search on the title field and then check that the price is between 0 - 9999 and that active is set to 1.
But both these queries seems to work fine on my test data. But what is the difference between them? Does the order "query" comes in play any diffrence?
Ignore the syntax, just take a look at the query structure.
First query
'filtered' => [
'query' => [
'match' => ['title' => Input::get('query')]
],
'filter'=> [
'bool' => [
'must' => [
['term' => [ 'active' => 1] ],
[ 'range' => [
'price' => [
'gte' => 1,
'lte' => 99999,
]
]
]
]
]
],
],
Second query
'filtered' => [
'filter' => [
'bool' => [
'must' => [
['term' => [ 'status' => 1] ],
[
'range' => [
'price' => [
'gte' => 1,
'lte' => 99999,
]
]
]
]
]
],
'query' => [
'match' => [
'title' => Input::get('query', '')
]
]
]
Thanks in advance.
It makes no difference at all in which order filter and query are mentioned in a filtered query. What dictates if query or filter is executed first for a document depends on an expert-level optional field called strategy of filtered query. For more information, read this.