Elastic search query according to MySQL Group by clause - elasticsearch

I am using Elasticsearch I want to write a query for getting unique record on the basis of query and group:
SELECT * from users where name='%john%', age='21', location='New York' group by name
Could you please let me know how to write the query in elasticsearch with query.

It would go something like this. You need a filtered query with a query_string in the query part to match *john* and then two filters in the filter part to match the age and the location. Finally, the grouping is achieved using a terms aggregation.
{
"query": {
"query": {
"query_string": {
"query": "*john*",
"default_field": "name"
}
},
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"age": 21
}
},
{
"term": {
"location": "New York"
}
}
]
}
}
}
},
"aggs": {
"group_by_name": {
"terms": {
"field": "name"
}
}
}
}

Related

Elasticsearch conditional query for nested array

Using the following document, I'm trying to perform an Elasticsearch keyword query, conditionally excluding field data from the scope of the search. Is this possible?
{
"Name":"doc1",
"UserData":[
{
"EnteredBy":"Eric",
"Description":"Desc entered by Eric, abc"
},
{
"EnteredBy":"Alex",
"Description":"Desc entered by Alex, def"
}
]
}
The Elasticsearch query I need will allow me to search across the whole document, except it should exclude from the search UserData items where EnteredBy does not match the specified user.
The following queries would return results:
User:Eric doc1
User:Eric abc
User:Alex doc1
User:Fred doc1
The following queries would not return results:
User:Eric def
User:Fred def
Everything I've tried thus far, ends up filtering content based on the presence of UserData nodes which apply to the specified user. I can't think of a way to specify that a field should be searched, only if the EnteredBy field matches.
I could restructure the document, if that would solve the problem.
Edit 1
The index..
PUT index1
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
},
"mappings": {
"properties" : {
"UserData" : {
"type":"nested"
},
"Name": {
"type":"text"
}
}
}
}
Edit 2
The query below is providing the results that I need, except for the child entity, I have to search in a specific field. If I change the second condition of the nested search into a query_string search, then it no longer uses the EnteredBy condition.
GET index1/_search
{
"query": {
"bool": {
"should": [
{
"nested":
{
"path": "UserData",
"query": {
"bool": {
"must": [{
"match": {
"UserData.EnteredBy": "Eric"
}},
{
"match": {
"UserData.Description": "def"
}
}]
}
}
}
},
{
"query_string":
{
"query": "doc1x"
}
}
]
}
}
}
This query appears to be working. I think I answered my own question.
GET index1/_search
{
"query": {
"bool": {
"should": [
{
"nested":
{
"path": "UserData",
"query": {
"bool": {
"must": [{
"match": {
"UserData.EnteredBy": "Eric"
}},
{
"query_string": {
"query": "def"
}
}]
}
}
}
},
{
"query_string":
{
"query": "doc1"
}
}
]
}
}
}

ElasticSearch Multi Match with Multiple Query Parameters

We have the following multi match query in Elastic Search
{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "90803",
"type": "cross_fields",
"fields": [
"POSTAL_CODE^5",
"ADDRESS",
"CITY"
],
"operator": "and"
}
}
}
}}
How can we pass multiple query parameters. For e.g. we want to pass multiple ID in the query to match against the field Postal Code.
First, is POSTAL_CODE an analyzed field? If it's not the case you could use a Terms Query:
{
"query": {
"terms" : {
"POSTAL_CODE" : ["90803", "90809"]
}
}
}
If you want to use Match for some reason, there is not a Match Query that matches several values, you have to use a Bool Query with should or must depending on your use case.
Example with must:
{
"query": {
"bool": {
"must": [{
"match": { "POSTAL_CODE": "90803" }
}, {
"match": { "POSTAL_CODE": "90809" }
}]
}
}
}

Elasticsearch filter with multi_match

I'm trying to write a query in ElasticSearch where I combine multi_match with filter for an id or a number og ids.
This is what i have so far:
{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "Kasper",
"fields": ["name", "first_name", "last_name"]
}
},
"filter": {
"term": {
"user_id": "ea7528f0-1b8a-11e8-a492-13e39bbd17cb"
}
}
}
}
}
The "must" part of the query works perfectly, and when I run it alone, I get two results.
When I pick out the "user_id" from one of the two results and adds the "filter" part of the query with that id, I get nothing.
What I really want to do is have something like in SQL where user_id in ('id1', 'id2'), so the filtering would be something like:
...,
"filter": {
"terms": {
"user_id": ["ea7528f0-1b8a-11e8-a492-13e39bbd17cb"]
}
}
Did I misunderstand something here?
I'm guessing that this is because user_id field is treated as a text and is analyzed. You should use keyword type in this situation (you need just change the mapping of user_id field.
Another way (if you are on Elasticsearch 5+) you can search in keyword subfield. Just try use below query:
{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "Kasper",
"fields": ["name", "first_name", "last_name"]
}
},
"filter": {
"term": {
"user_id.keyword": "ea7528f0-1b8a-11e8-a492-13e39bbd17cb"
}
}
}
}
}
I only changed "user_id" to "user_id.keyword" in your query.

How can we use exists query in tandem with the search query?

I have a scenario in Elasticsearch where my indexed docs are like this :-
{"id":1,"name":"xyz", "address": "xyz123"}
{"id":1,"name":"xyz", "address": "xyz123"}
{"id":1,"name":"xyz", "address": "xyz123", "note": "imp"}
Here the requirement stress that we have to do a term match query and then provide relevance score to them which is a straight forward thing but the additional aspect here is if any doc found in search result has note field then it should be given higher relevance. How can we achieve it with DSL query? Using exists we can check which docs contain notes but how to integrate with match query in ES query. Have tried lot of ways but none worked.
With ES 5, you could boost your exists query to give a higher score to documents with a note field. For example,
{
"query": {
"bool": {
"must": {
"match": {
"name": {
"query": "your term"
}
}
},
"should": {
"exists": {
"field": "note",
"boost": 4
}
}
}
}
}
With ES 2, you could try a boosted filtered subset
{
"query": {
"function_score": {
"query": {
"match": { "name": "your term" }
},
"functions": [
{
"filter": { "exists" : { "field" : "note" }},
"weight": 4
}
],
"score_mode": "sum"
}
}
}
I believe that you are looking for boosting query feature
https://www.elastic.co/guide/en/elasticsearch/reference/5.1/query-dsl-boosting-query.html
{
"query": {
"boosting": {
"positive": {
<put yours original query here>
},
"negative": {
"filtered": {
"filter": {
"exists": {
"field": "note"
}
}
}
},
"negative_boost": 4
}
}
}

How to pass list of values for a particular field in Elastic Search Query

I have a query to search for a provider_id from the Elastic Search Cluster. I am using the below query to get results for a single provider_id but need help in figuring out how can I pass a list of providers.
{
"query": {
"bool": {
"must": [{
"match": {
"message.provider_id": {
"query": 943523,
"type": "phrase"
}
}
}]
}
}
}
Suppose I want to search for provider_ids = [913523, 923523, 923523, 933523, 953523] then how should I modify the query?
You could index the provider_id as not_analyzed and then use a terms query:
POST /test_index/_search
{
"query": {
"terms": {
"message.provider_id": [
"913523", "923523", "923523", "933523", "953523"
]
}
}
}
or as a bool query with a filter if you are not going to need the score:
POST /test_index/_search
{
"query": {
"bool": {
"filter": [
{
"terms": {
"message.provider_id": [
"913523", "923523", "923523", "933523", "953523"
]
}
}
]
}
}
}

Resources