Filtering and matching with an elasticsearch query - elasticsearch

I am having trouble applying a secondary filter to my elasticsearch query below. Only the first filter is matching. I want both filters to apply to the query.
"query": {
"bool": {
"must": [
{
"bool": {
"filter": {
"range": {
"#timestamp": {
"gte": "2019-03-12",
"lte": "2019-03-13"
}
}
}
}
},
{
"bool": {
"filter": {
"bool": {
"must": {
"match": {
"msg_text": "foo AND bar"
}
}
}
}
}
}
]
}
}

Well I've mentioned two solutions, first one makes use of Match Query while the second one makes use of Query String.
Also I'm assuming msg_text field is of type text.
Difference is that, query_string uses a parser, that would parse the text you mention based on the operators like AND, OR.
While match query would read the text, analyse the text and based on it constructs a bool query. In the sense you don't need to mention operators and it won't work
You can read more about them in the links I've mentioned.
1. Using Match Query
POST <your_index_name>/_search
{
"query":{
"bool":{
"filter":{
"bool":{
"must":[
{
"range":{
"#timestamp":{
"gte":"2019-03-12",
"lte":"2019-03-13"
}
}
},
{
"match":{
"msg_text":"foo bar"
}
}
]
}
}
}
}
}
2. Using Query String
POST <your_index_name>/_search
{
"query":{
"bool":{
"filter":{
"bool":{
"must":[
{
"range":{
"#timestamp":{
"gte":"2019-03-12",
"lte":"2019-03-13"
}
}
},
{
"query_string":{
"fields": ["msg_text"], <----- You can add more fields here using comma as delimiter
"query":"foo AND bar"
}
}
]
}
}
}
}
}
Technically nothing is wrong with your solution, in the sense, it would work, but I hope my answers clear, simplifies the query and helps you understand what you are trying to do.
Let me know if it helps!

Related

what is purpose in must nested in filter elasticsearch?

what's difference between the following es filter query?
1. filter context for multi query conditions:
{
"query": {
"bool": {
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
must in filter context:
{
"query": {
"bool": {
"filter": [
{
"bool": {
"must": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
]
}
}
}
The first query is used in scenarios where you just want to filter using AND operator on different fields. By default if you write filter query in this way, it would be executed as AND operation.
The second query, in your case/scenario, does exactly as the first query (no difference, just two ways of doing same thing), however the reason we can "also" do that is to implement/cover more complex filter use-cases that uses many different AND and OR combinations.
Note that in Elasticsearch AND is represented by must while OR is represented by should clauses.
Let's say I would want to filter a scenario like I want all documents having
sales from department 101 or
sales from department 101B along with price > 150.
You probably would have to end up writing query in the below way:
POST sometestindex/_search
{
"query":{
"bool":{
"filter":[
{
"bool":{
"should":[
{
"term":{
"dept.keyword":"101"
}
},
{
"bool":{
"must":[
{
"term":{
"dept.keyword":"101B"
}
},
{
"range":{
"price":{
"gte":150
}
}
}
]
}
}
],
"minimum_should_match": 1
}
}
]
}
}
}
In short, for your scenario, first query is just a short-hand way of writing the second-query, however if you have much more complex filter logic, then you need to leverage the Bool query inside your filter as you've mentioned in your second query, as I've mentioned in the sample example.
Hope that clarifies!

Elasticsearch: How to combine regex query with filter

I have a search that in some situations needs to be searched by a regex query
GET my-index/_search
{
"query": {
"regexp":{
"name":".*something.*"
}
}
}
And sometimes needs to be filtered, like so:
GET /my-index/_search
{
"query":{
"bool":{
"filter":[
{
"term":{
"createdByEmail.keyword":"me.email#example.com"
}
}
]
}
}
I want to combine these 2 so that it will only show me resolts where the name matches the regex AND the createdByEmail matches the email address I'm sending in.
You can add first query inside must clause of second as below:
{
"query": {
"bool": {
"must": [
{
"regexp": {
"name": ".*something.*"
}
}
],
"filter": [
{
"term": {
"createdByEmail.keyword": "me.email#example.com"
}
}
]
}
}
}

how to know which keywords matched in elasticsaearch

Say that I query:
POST /story/story/_search
{
"query":{
"bool":{
"should":[
{
"match":{
"termVariations":{
"query":"not driving",
"type":"boolean",
"operator":"AND"
}
}
},
{
"match":{
"termVariations":{
"query":"driving",
"type":"boolean",
"operator":"AND"
}
}
}
]
}
}
}
This query returned by one analyzer or another 3 documents.
How do I tell which should clause was matched? Can Elasticsearch return the matched phrase along with the result?
Thanks!
The best option here would be named queries.
You can name your query and the name of the queries that matched would be provided per document.
{
"query": {
"bool": {
"should": [
{
"match": {
"name.first": {
"query": "qbox",
"_name": "first"
}
}
},
{
"match": {
"name.last": {
"query": "search",
"_name": "last"
}
}
}
]
}
}
}
Thanks #keety! highlight was exactly what I was looking for!! :-)

multiple search conditions in one query in es and distinguish the items according to the conditions

For one case I need to put multiple search conditions in one query to reduce the number of queries we need.
However, I need to distinguish the returning items based on the conditions.
Currently I achieved this goal by using function score query, specifically: each condition is assigned with a score, and I can differentiate the results based on those scores.
However, the performance is not that good. Plus now we need to get the doc count of each condition.
So is there any way to do it? I'm thinking using aggregation, but not sure if I can do it.
Thanks!
update:
curl -X GET 'localhost:9200/locations/_search?fields=_id&from=0&size=1000&pretty' -d '{
"query":{
"bool":{
"should":[
{
"filtered":{
"filter":{
"bool":{
"must":[{"term":{"city":"new york"}},{"term":{"state":"ny"}}]
}
}
}
},
{
"filtered":{
"filter":{
"bool":{
"must":[{"term":{"city":"los angeles"}},{"term":{"state":"ca"}}]
}
}
}
}
]
}
}}'
Well to answer the first part of your question , names queries are the best.
For eg:
{
"query": {
"bool": {
"should": [
{
"match": {
"field1": {
"query": "qbox",
"_name": "firstQuery"
}
}
},
{
"match": {
"field2": {
"query": "hosted Elasticsearch",
"_name": "secondQuery"
}
}
}
]
}
}
}
This will return an additional field called matched_queries for each hit which will have the information on queries matched for that document.
You can find more info on names queries here
But this this information cant be used for aggregation.
So you need to handle the second part of your question in a separate manner.
Filter aggregation for each query type would be the idea solution here.
For eg:
{
"query": {
"bool": {
"should": [
{
"match": {
"text": {
"query": "qbox",
"_name": "firstQuery"
}
}
},
{
"match": {
"source": {
"query": "elasticsearch",
"_name": "secondQuery"
}
}
}
]
}
},
"aggs": {
"firstQuery": {
"filter": {
"term": {
"text": "qbox"
}
}
},
"secondQuery": {
"filter": {
"term": {
"source": "elasticsearch"
}
}
}
}
}
You can find more on filter aggregation here

Using filter beside query_string in Elastic Search

How to full text search and have filter? I want to search for a text among documents with language_id=10. I've tried it this way:
{
"query": {
"query_string": {
"query": "Declared"
},
{
"filtered": {
"filter": {
"term": {
"language_id": 10
}
}
}
}
}
}
but seems like it's not correct. How to correct it?
In version 5.2, filtered query is replaced by the bool query, and returns error on my Elastic 5.2 instance. See here.
The new syntax is:
{
"query":{
"bool":{
"must":{
"query_string":{
"query":"Declared"
}
},
"filter":{
"term":{
"language_id":10
}
}
}
}
}
Yep, the syntax of the filtered query is a bit cumbersome. AFAIK it should look like that:
{
"query":{
"filtered":{
"query":{
"query_string":{
"query":"Declared"
}
},
"filter":{
"term":{
"language_id":10
}
}
}
}
}
Sorry Ashalynd but the filter is not placed a the right place in your answer.
This is working better:
{
"query":{
"filtered":{
"query":{
"query_string":{
"query":"Declared"
}
},
"filter":{
"term":{
"language_id":10
}
}
}
}
}

Resources