Elastic Search : Search keyword results of a specific category - elasticsearch

I'm trying to build a query where I'm trying to search for names of people of a specific country. If I provide input as John and USA, I should only find results of people by the name John (by the property : name) from USA (by the property : country) and results from other countries shouldn't appear in the results.
What I have tried :
"query": {
"bool": {
"should": [
{
"multi_match": {
"query": "John",
"fields": ["username", "first_name", "last_name"],
"fuzziness": "AUTO",
"minimum_should_match": "50%"
}
}
],
"filter": [
{
"match": {
"country": "USA"
}
},
{
"match": {
"is_citizen": true
}
}
]
}
}
With the above query the problem I'm seeing is that the results also show people **who don't have their name as John but are from USA
**.
Expectation : To filter results of given keyword specific to given country.

Instead of using should you need to use must clause in your name query.
Below query should give you expected results. refer boolean query official doc to understand the difference with examples.
"query": {
"bool": {
"must": [ --> note `must` here
{
"multi_match": {
"query": "John",
"fields": ["username", "first_name", "last_name"],
"fuzziness": "AUTO",
"minimum_should_match": "50%"
}
}
],
"filter": [
{
"match": {
"country": "USA"
}
},
{
"match": {
"is_citizen": true
}
}
]
}
}

You are using should clause thats why it is not working. You can use must insted of should and it will resolved your issue.
You can use "type":"phrase_prefix" to match Jo with John.
You can change your query as shown below and it will work:
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "John",
"fields": ["username", "first_name", "last_name"],
"type":"phrase_prefix",
"minimum_should_match": "50%"
}
}
],
"filter": [
{
"match": {
"country": "USA"
}
},
{
"match": {
"is_citizen": true
}
}
]
}
}

Related

Querying fields with AND in ElasticSearch

In my ElasticSearch document index I have a property type like
type= LOCATION | PERSON | TIME
and a text field that represents the whole document.
To search for types like LOCATION and a specific text like `Mountain View" I do like
doc.text:Mountain View AND doc.type:LOCATION
If I want to do a OR query I would use instead the query_string approach like
"query": {
"query_string": {
"query": "entity.text: (Mountain View OR Menlo Park) AND entity.type:LOCATION"
}
}
This works as well. To do AND queries, like searching for item.text having both "Mountain View" and "Menlo Park" for a item.type=LOCATION, it does not work doing like
"query": {
"query_string": {
"query": "entity.text: (California AND Nevada) AND entity.type:LOCATION"
}
}
Other attempts were:
Using bool clause with should like:
{
"query": {
"bool": {
"should": [
{ "match": { "text": "Menlo Park" }},
{ "match": { "text": "Mountain View" }}
]
}
}
}
Using cross-fields with multi_match
"query": {
"multi_match": {
"query": "California Nevada",
"type": "cross_fields",
"operator": "AND",
"fields": [
"text"
]
}
}
Another approach was using must with the latter (in this case omitting the type by the way):
{
"query": {
"bool": {
"must": [
{
"multi_match" : {
"query": "Nevada",
"type": "cross_fields",
"fields": [ "text"],
}
},
{
"multi_match" : {
"query": "California",
"type": "cross_fields",
"fields": [ "text" ]
}
}
]
}
}
}
but it returns no results neither. Note that in the last case using should instead of must will produce an OR query that will work ok.
So how to perform an AND query on the same field text to match multiple values like California and Nevada?
If I understood the question right, I would do the following:
{
"query": {
"bool" : {
"must": [
"match" : {
"text" : {
"query" : "California Nevada",
"operator" : "and"
}
}
]
}
}
}
Documentation
Hope it helps!

how to use SHOULD inside MUST in elasticsearch6?

I am very new to elasticsearch trying to understand things better but struggling a bit. I am trying to write query with AND(must) and OR(should) condition. Below elasticsearch query works good. But I need one more zipcode to be added in the condition, it should be or between 2 zipcodes.
Working Query:
{
"_source": {
"includes": [
"Name",
"Address",
"Contact"
]
},
"query": {
"bool": {
"must": [
{
"query_string": {
"fields": [
"firstName",
"lastName",
"middleName"
],
"query": "*andy*"
}
},
{
"match": {
"zipcode": "55555"
}
}
]
}
}
}
how to add zipcode value match in OR condition?
You can either replace match by terms:
{
"terms": {
"zipcode": ["55555", "55556"]
}
}
Or you can add two match clauses in a bool/should:
"bool": {
"must": [
{
"query_string": {
"fields": [
"firstName",
"lastName",
"middleName"
],
"query": "*andy*"
}
}
],
"minimum_should_match": 1,
"should": [
{
"match": {
"zipcode": "55555"
}
},
{
"match": {
"zipcode": "55556"
}
}
]
}

Elastic : search two terms, one on _all, other one on a field

I would like to mix a search on a whole document (eg "developer") and a search on some field for another term (eg "php").
I can do each search separately but I can't mix them.
Here my example (simplified to show only my issue) :
{
"query": {
"function_score": {
"query": {
"match": {
"_all": "developer"
},
"multi_match": {
"query": "php",
"fields": [
"skills.description",
"skills.description",
"skills.details"
],
"operator": "or",
"type": "most_fields"
}
}
}
}
If I run this example I have an error :
Parse Failure [Failed to parse source
Is there a way to search on both _all and specific fields with two terms?
Thanks.
Yes, you're almost there, you need to combine them into a bool/must query:
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"match": {
"_all": "developer"
}
},
{
"multi_match": {
"query": "php",
"fields": [
"skills.description",
"skills.description",
"skills.details"
],
"operator": "or",
"type": "most_fields"
}
}
]
}
}
}
}
}

Elasticsearch: Conditionally filter query on fields if they exist in multi-index query

I have a query for a general search which spans multiple indices. Some of the indices have a field called is_published and some have a field called date_review, some have both.
I'm struggling to write a query which will search across fields and filter on the fields mentioned above but only if they exist. I have managed to achieve what I want on the individual fields using missing and/or exists, but it excludes the other variants.
In english, I want to keep documents in the result where:
is_published is true OR the field does not exist
date_review is in the future OR the field does not exist
So, if a document has is_published and it's false, remove it. If a document has date_review in the past, remove it. If it has is_published == false and date_review is in the future, remove it.
I hope this makes sense?
For the purpose of answering, assume the documents might look like this:
// Has `is_published` flag
{
"label": "My document",
"body": "Lorem ipsum doler et sum.",
"is_published": true
}
// Has `date_review` flag
{
"label": "My document",
"body": "Lorem ipsum doler et sum.",
"date_review": "2017-01-01"
}
// Has both `is_published` and `date_review` flags
{
"label": "My document",
"body": "Lorem ipsum doler et sum.",
"is_published": true
"date_review": "2017-01-01"
}
At the moment, my [unfiltered] query looks like this:
{
"index": "index-1,index-2,index-3",
"type": "item",
"body": {
"query": {
"filtered": {
"query": {
"multi_match": {
"query": "my serach phrase",
"type": "phrase_prefix",
"fuzziness": null,
"fields": [
"label^3",
"body",
]
}
},
"filter": []
}
}
}
}
Very grateful for any pointers.
Thanks.
You can try a query like this one:
{
"query": {
"filtered": {
"query": {
"multi_match": {
"query": "my serach phrase",
"type": "phrase_prefix",
"fuzziness": null,
"fields": [
"label^3",
"body"
]
}
},
"filter": {
"bool": {
"must": [
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"missing": {
"field": "is_published"
}
},
{
"term": {
"is_published": true
}
}
]
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"missing": {
"field": "date_review"
}
},
{
"range": {
"date_review": {
"gt": "now"
}
}
}
]
}
}
]
}
}
}
}
}

ElasticSearch How to AND a nested query

I am trying to figure out how to AND my Elastic Search query. I've tried a few different variations but I am always hitting a parser error.
What I have is a structure like this:
{
"title": "my title",
"details": [
{ "name": "one", "value": 100 },
{ "name": "two", "value": 21 }
]
}
I have defined details as a nested type in my mappings. What I'm trying to achieve is a query where it matches a part of the title and it matches various details by the detail's name and value.
I have the following query which gets me nearly there but I haven't been able to figure out how to AND the details. As an example I'd like to find anything that has:
detail of one with value less than or equal to 100
AND detail of two with value less than or equal to 25
The following query only allows me to search by one detail name/value:
"query" : {
"bool": {
"must": [
{ "match": {"title": {"query": titleQuery, "operator": "and" } } },
{
"nested": {
"path": "details",
"query": {
"bool": {
"must": [
{ "match": {"details.name" : "one"} },
{ "range": {"details.value" : { "lte": 100 } } }
]
}
}
} // nested
}
] // must
}
}
As a second question, would it be better to query the title and then move the nested part of the query into a filter?
You were so close! Just add another "nested" clause in your outer "must":
POST /test_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "title",
"operator": "and"
}
}
},
{
"nested": {
"path": "details",
"query": {
"bool": {
"must": [
{"match": {"details.name": "one" } },
{ "range": { "details.value": { "lte": 100 } } }
]
}
}
}
},
{
"nested": {
"path": "details",
"query": {
"bool": {
"must": [
{"match": {"details.name": "two" } },
{ "range": { "details.value": { "lte": 25 } } }
]
}
}
}
}
]
}
}
}
Here is some code I used to test it:
http://sense.qbox.io/gist/1fc30d49a810d22e85fa68d781114c2865a7c92e
EDIT: Oh, the answer to your second question is "yes", though if you're using 2.0 things have changed a little.

Resources