bool query with filter does not return any documents - elasticsearch

The simple query
"query": {
"simple_query_string": { "query":"great guide" }
},
returns my document as expected, containing
"groups": [
"Local Business"
],
But if I use a filter, it returns no documents:
"query": {
"bool":{
"must":[
{"simple_query_string": { "query":"great guide" }}
],
"filter":{
"terms":{
"groups":["Local Business"]
}
}
}
},
If I remove the "filter" key and values, then the document is retrieved.
Why isn't the filter matching the document ?

If the groups field is of type keyword, then the query you've mentioned works as expected.
However it wouldn't work if the field groups if of type text. In that case the below query would actually fit what you are looking for.
Query for group - Type text
POST <your_index_name>/_search
{
"query":{
"bool":{
"must":[
{
"simple_query_string":{
"query":"great guide"
}
}
],
"filter":{
"match":{
"groups":"Local Business"
}
}
}
}
}
The reason the query you've mentioned doesn't work for the field of type text is because this field goes through Analysis phase making use of Standard Analyzer by default where it would first convert Local Business into small cases and then saves local and business as two individual words in the inverted index.
Elasticsearch would only give you results if the words you query match what's available in the index.
And what keyword does is, it saves Local Business as is in inverted index.
Note: You can try the query you have by replacing groups with groups.keyword if mapping hasn't been defined and is created dynamically.
Hope this helps!

Related

Elasticsearch sort exact matches and fuzzy matches in different sets

This is my first ever question here so I apologize if I make any mistakes.
I'm trying to make a fuzzy search (match query with fuzziness parameter) on my index that will return the results in Alphabetical order. But I need the exact matches to come first(Alphabetically ordered among themselves) and fuzzy matches later.
I have tried this to make exact matches have higher scores. But they are just being sorted by their scores:
"query":{
"bool":{
"must":[
{
"match":{
"myPropertyName":{
"query":"myWord",
"fuzziness":"AUTO"
}
}
}
],
"should":[
{
"match":{
"myPropertyName":{
"query":"myWord",
"boost":20
}
}
}
]
}
},
"sort":[
"_score",
{
"myProperty.keyword":{
"order":"asc"
}
}
],
"track_scores":true
}
Then I have tried to make the scores of all exact matches and fuzzy matches same among themselves with many methods. I can make it for fuzzy matches by using filter or constant_score but I couldn't figure a way to assign a custom score to the results of should query in my search.
How can I achieve this?
I've managed to achieve this by using a function score query with "boost_mode": "replace" and setting a custom value to weight parameter like: "weight": "10".
{
"query":{
"function_score":{
"query":{
"bool":{
"filter":[
{
"match":{
"myPropertyName":{
"query":"myWord",
"fuzziness":"AUTO"
}
}
}
]
}
},
"boost_mode":"replace",
"functions":[
{
"filter":{
"match":{
"myPropertyName":{
"query":"myWord"
}
}
},
"weight":"10"
}
]
}
},
"sort":[
"_score",
{
"myProperty.keyword":{
"order":"asc"
}
}
],
"track_scores":true
}
This way documents that match the match query will return with 0 score since it's also a filter query. Then among these documents the ones that match the function will return with 10 score since "boost_mode": "replace" and "weight: "10".
When it comes to sorting firstly Elasticsearch will sort the results by their score's since it comes first in "sort[]" array. Then documents with same scores will be sorted alphabetically among themselves.
This worked perfectly for me.

Add simple search on every field in ElasticSearch

here's my query:
"query":{
"query":{
"bool":{
"must":[
{
"term":{
"device_id":"1"
}
},
{
"range":{
"created_at":{
"gte":"2019-10-01",
"lte":"2019-12-10"
}
}
}
],
"must_not":[
{
"term":{
"action":"ping"
}
},
{
"term":{
"action":"checkstatus"
}
}
]
}
},
"sort":{
"created_at":"desc"
},
"size":10,
"from":0
}
the logs vary a lot with completely different set of fields. What I can do to search if in any of them is a string that I'm looking for? Let's say I'm looking for "mit" and it shows me one log with
surname -> Smith
and the second one with
action -> "message comMITted"
I've tried using match [ '_all' => "mit" ] but it's deprecated I heard.
I'm using Elasticsearch 7.3.1
To perform search across all fields, use copy_to to copy the values of all fields into a grouped field, and perform the queries against that field. In case you have dynamic index mappings refer this.
For supporting infix matching, you can use ngrams. This is a good tutorial for ngrams.
Infix matching can be performed using wildcard query too. But it's not recommended due to performance reasons.

Not getting where data with filter (elastic search 6.4)

elasticsearch version: 6.4
Here is my current data:
I want to search for products which has Xbox in name. I am using the match keyword but that is not working.
Below is my elastic search query:
{
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "xbox"
}
}
},
{
"terms": {
"deep_sub": [
"Konsol Oyunları",
"Konsol Aksesuarları"
]
}
}
]
}
},
"from": 0,
"size": 50
}
Whenever you face such kind of issues, try breaking down the query. You have Match Query and Term Query. Run both of them individually and see what's not working.
From what I understand, looks like your field deep_sub is of text type and this would mean Term Query is not returning results.
You would need to create its sibling equivalent using keyword type and then run Term Query on it for exact matches.
From the above link we have the below info:
Keyword fields are only searchable by their exact value.
If you do not control the mapping, meaning if your mapping if of dynamic type, then you must have its sibling equivalent keyword field available which would be deep_sub.keyword
You can check by running GET <your_index_name>/_mapping
Your query would then be as follows:
POST <your_index_name>/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"name":{
"query":"xbox"
}
}
},
{
"terms":{
"deep_sub.keyword":[ <----- Change This
"Konsol Oyunları",
"Konsol Aksesuarları"
]
}
}
]
}
},
"from":0,
"size":50
}
Let me know if this helps!

Elasticsearch post_filter on nested types not filtering on aggregations

Hello Elasticsearch gurus, I need your help!
We're using Elasticsearch v5.4 and
I have multiple nested types in elasticsearch in the form of:
"testLookup" : [
{
"id": 1001,
"name": "test1"
},
{
"id": 1002,
"name": "test2"
}
]
which I'm trying to display the names as checkbox options in a filter.
I was trying to use the post_filter top level element to basically filter the aggregations so I can update and display ONLY the affected filter options, kinda like how it is being used on this demo site: http://demo.searchkit.co
"post_filter": {
"bool":{
"must": [
{
"nested" : {
"path" : "testLookup",
"query": {
"bool": {
"filter":{
"bool":{
"should":[
{ "term": { "perTestLookup.name.keyword": "Adele"}}
]
}
}
}
}
}
},
{
"nested" : {
"path" : "testLookup2",
"query": {
"bool": {
"filter":{
"bool":{
"should":[
{ "term": { "perTestLookup2.name.keyword": "Gene" }}
]
}
}
}
}
}
}
]
}
}
If i'm not mistaken I think what the post_filter does is apply the filter for each of the aggregations before the search request is sent, which you can observe that by looking into the request payload of the search filter after you click one of the filter checkboxes.
However, I can not get the post_filter to apply the filters to the aggregations, the filters are just not being applied. Why is this the case? is post_filter for nested types not supported?
Any tips or guidance will be greatly appreciated. Thank you!
Note: I do not have any searchkit experience.
The post_filter in an Elasticsearch request is executed after the aggregations are calculated to reduce the hits result further. See the docs about post_filter.
The idea behind this is the fact that in a faceted search (i.e. imagine filtering by category), you still want to retrieve that category counts for all categories in your aggregations, but you want to filter for that clicked category in your the documents you are searching.
So this is expected behaviour from the Elasticsearch perspective.

elastic search get bucket count

I have the following query:
GET images/_search
{
"query":{
"bool":{
"must":[
{
"term":{
"appID.raw":"myApp"
}
}
]
}
},
"size":0,
"aggs":{
"perDeviceAggregation":{
"terms":{
"field":"deviceID",
"min_doc_count":50000
}
}
}
}
This query returns a "buckets" array, but I would like to return only the length of the array, without the array itself.
Explanation: the purpose of this query is to count how many devices that belong to app "myApp", have over 50,000 images. I don't need the query to return these devices, just to know how many are there.
The terms aggregation returns buckets -- 1 bucket for each unique term of the field -- where each bucket contains the count of documents that contain the term.
It sounds like you want to know the number of unique terms instead of the document count per term. This concept is called cardinality.
There is a different aggregation to determine cardinality. Your query would look like this:
GET images/_search
{
"query":{
"bool":{
"must":[
{
"term":{
"appID.raw":"myApp"
}
}
]
}
},
"size":0,
"aggs":{
"deviceIdCardinality":{
"cardinality":{
"field":"deviceID"
}
}
}
}
NOTE: cardinality counts are approximate. You can configure the accuracy with the precision_threshold parameter to the aggregation. See the documentation for specifics.

Resources