Diference between term and match in Elasticsearch in a bool query - elasticsearch

I have a simple document where the _source looks like:
{
"name" : "myProduct",
"label" : "isApiisApi",
"isApi" : 1,
"sold" : 0
}
I've been trying to create a multiple condition query using bool. The only way that I get it working was by using a match query:
{
"query": {
"bool": {
"must": [
{ "term": { "sold": 0 } },
{ "term": { "isApi": 1 } },
{ "match": { "name": "myProduct" } }
]
}
}
}
But why doesn't it work when I use the term query (as the final condition):
{
"query": {
"bool": {
"must": [
{ "term": { "sold": 0 } },
{ "term": { "isApi": 1 } },
{ "term": { "name": "myProduct" } }
]
}
}
}

Tldr;
Elastic text fields upon ingestion passes the data into a analyzer.
By default the standard analyzer is used. Which comes with a token filter named Lowercase.
Your text is indexed in lowercase.
But you are using a term which search for exact match on the indexed data.
In your case myproduct =/= myProduct.
To Reproduce
By default Elastic index, all string like data in two fields.
text
keyword
For exact match you want to use the keyword version.
See below:
POST /72020272/_doc
{
"name" : "myProduct",
"label" : "isApiisApi",
"isApi" : 1,
"sold" : 0
}
GET /72020272/_mapping
GET /72020272/_search
{
"query": {
"bool": {
"must": [
{ "term": { "sold": 0 } },
{ "term": { "isApi": 1 } },
{ "term": { "name": "myProduct" } }
]
}
}
}
GET /72020272/_search
{
"query": {
"bool": {
"must": [
{ "term": { "sold": 0 } },
{ "term": { "isApi": 1 } },
{ "term": { "name.keyword": "myProduct" } }
]
}
}
}

Related

Elasticsearch constant_score wrapped inside must does not return expected result

I have the following ES query :
{
"query": {
"bool": {
"should": [
{
"constant_score": {
"boost": 5,
"filter": {
"bool": {
"must": [
{
"ids": {
"values": [
"winnerAthlete-A"
]
}
},
{
"dis_max": {
"queries": [
{
"bool": {
"filter": {
"term": {
"isAthlete": true
}
}
}
},
{
"bool": {
"filter": {
"term": {
"isWinner": true
}
}
}
}
]
}
}
]
}
}
}
},
{
"constant_score": {
"boost": 4,
"filter": {
"bool": {
"must": [
{
"ids": {
"values": [
"winnerAthlete-B"
]
}
},
{
"dis_max": {
"queries": [
{
"bool": {
"filter": {
"term": {
"isAthlete": true
}
}
}
},
{
"bool": {
"filter": {
"term": {
"isWinner": true
}
}
}
}
]
}
}
]
}
}
}
}
]
}
}
}
It does return the result I expect : the 2 documents winnerAthlete-A and winnerAthlete-B, assigning a score of 5.0 to winnerAthlete-A and a score of 4.0 to winnerAthlete-B.
Now, when I turn the should on the third line of the query into a must, the query does not match any document whereas I would expect the exact same result. I can't wrap my head around why. I have tried using the ES _explain keyword to understand why this query doesn't match when using must but it didn't help me.
Any idea why this query rewritten with a must does not return anything whereas the should version does return the expected result ?
Should works like "OR" . It will return a document which matches any of clauses.
Must works like "AND" . Document must satisfy both clauses.
Your query is not returning any result because there is no single document which has ids as winnerAthlete-A as well as winnerAthlete-B

Elasticsearch query with Must (and) Should (or) not producing desired results

I'm trying to perform a query of X AND (y OR z)
I need to get all the sold properties that the agent was either the listing agent or the selling agent.
With only the bool must I get 9324 results. When I add the bool should, I get the same result set of 9324. The agent with the ID of 140699 should have only about 100 results. I've also tried a bool filter with no success. When replacing the should with a filter, the result is like another bool must, and I only get results where the agent was the listing agent AND the selling agent
GET /property/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"statusCatID": {
"value": "Sold"
}
}
},
{
"range": {
"closingDate": {
"gte": "now-3M"
}
}
}
],
"should": [
{
"term": {
"listAgent1": {
"value": 140699
}
}
},
{
"term": {
"sellingAgent1": {
"value": 140699
}
}
}
]
}
},
"size": 300
}
With your notation you are performing a query like this:
(statuscatid:sold AND closingDate:now-3M OR listAgent1:140699 OR sellingAgent1:140699)
I suggest you to read this official blog post to understand better the bool queries in elastic. If you want a query like this:
(statuscatid:sold AND closingDate:now-3M) AND (listAgent1:140699 OR sellingAgent1:140699)
You should write it in this way:
{
"query": {
"bool": {
"must": [
{
"term": {
"statusCatId": "sold"
}
},
{
"range": {
"closingDate": "now-3M"
}
},
{
"bool": {
"should": [
{
"term": {
"listAgent1": 140699
}
},
{
"term": {
"sellingAgent1": 140699
}
}
]
}
}
]
}
},
"size": 300
}

How to join two queries in one using elasticsearch?

Hi I want to join two queries in one in elasticsearch, but I don't know how to do it: I think I should do an aggregation but I don't know very clear how to do it. Could you help me? My ES version is 5.1.2.
First filter by status and name:
POST test_lite/_search
{
"aggs": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"match": {
"STATUS": "Now"
}
},
{
"match": {
"NAME": "PRUDENTL"
}
}
]
}
}
}
}
}
Look for in the filtered records for the word filtered in description:
POST /test_lite/_search
{
"query": {
"wildcard" : { "DESCRIPTION" : "*english*" }
}
}
The only query needed is:
POST test_lite/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"STATUS": "Now"
}
},
{
"match": {
"NAME": "PRUDENTL"
}
},
{"wildcard" : { "DESCRIPTION" : "*english*" }}
]
}
}
}

How to combine term filters with a missing filter in Elasticsearch?

We are using Elasticsearch 1.6 and I have a working three term query that I need to modify with a stand alone working missing filter. Here is the current code:
The original term query with three entries
GET ...
{
"query": {
"nested": {
"path": "MAIN_FIELD",
"query": {
"bool": {
"must": [
{
"term": {
"MAIN_FIELD.ID": 1234
}
},
{
"term": {
"MAIN_FIELD.OTHER_IND": "false"
}
},
{
"term": {
"MAIN_FIELD.INDICATOR": "Y"
}
}
]
}
}
}
}
}
The stand alone missing query:
GET ...
{
"query" : {
"filtered" : {
"filter" : {
"missing" : { "field" : "MAIN_FIELD.OTHER_IND" }
}
}
}
}
How do I change the term query from the first query:
"term": {
"MAIN_FIELD.OTHER_IND": "false"
}
to use a missing filter?
I think what you want is below:
{
"query": {
"nested": {
"path": "MAIN_FIELD",
"query": {
"bool": {
"must": [
{
"term": {
"MAIN_FIELD.ID": 1234
}
},
{
"filtered": {
"filter": {
"missing": {
"field": "MAIN_FIELD.OTHER_IND"
}
}
}
},
{
"term": {
"MAIN_FIELD.INDICATOR": "Y"
}
}
]
}
}
}
}
}

Search for records in elastic search with set of values for each field.

I have a set of records in elastic search
I want to compare 1 specific records (I have it with me in a variable) with rest of the records present in the index.
I want to compare values for each field individually with the values from the record that i have.
For eg.
If i have
{
"person" : [
{
"name" : "asd",
"awdawD" : "asdawd"
},
{
"name" : "adw ed",
"awdawD" : "asdawd"
},
{
"name" : "a wra",
"awdawD" : "asdawd"
},
{
"name" : "ca eyy",
"awdawD" : "asdawd"
}
]
}
and my record is
[
{
"name" : "asd",
"awdawD" : "asdawd"
},
{
"name" : "s tr",
"awdawD" : " tjy"
}
]
I want to compare name with name, awdawD with awdawD and get the result.
Since I have an array of Persons, will i have to create a loop for each element in the records I have, to compare it with the records in elastic search?
How can I do this in elastic search with out the loop ?
Comparing each name and awdawD individually.
I know it's probably not the elegant solution you're looking for (which I don't think exists), but you could always do something like this:
POST /test_index/_search
{
"query": {
"filtered": {
"filter": {
"or": {
"filters": [
{
"and": {
"filters": [
{
"term": {
"name": "asd"
}
},
{
"term": {
"awdawD": "asdawd"
}
}
]
}
},
{
"and": {
"filters": [
{
"term": {
"name": "s tr"
}
},
{
"term": {
"awdawD": " tjy"
}
}
]
}
}
]
}
}
}
}
}
or this
POST /test_index/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"name": "asd"
}
},
{
"match": {
"awdawD": "asdawd"
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"name": "s tr"
}
},
{
"match": {
"awdawD": " tjy"
}
}
]
}
}
]
}
}
}
Both of these queries return only your first document (one or the other may be preferable depending on your analysis setup).
Here is some code I used to test it out:
http://sense.qbox.io/gist/52de7f75e685486a63d18bd387cbb02d03cc6feb

Resources