Sorting results in Elastic - sorting

Trying to sort query results now. Neither of the queries below works:
{
"sort": [
{
"name": {
"order": "asc"
}
}
],
"query": {
"match_all": {}
}
}
{
"query": {
"match_all": {}
},
"sort": [
{
"name": {
"order": "asc"
}
}
]
}
even though they seem to be valid, according to the (documentation). What am I missing here? And by the way, does the order of query parts matters at all in Elastic?

i have faced same case.If your name field mapped as string and anlayzed then query never works. Use multi field type where you can map name twice, one as string and analyzed and another as string and not analyzed. For Ex
'user_id' =>array('type'=>'integer'),
'name' =>array(
'type'=>'multi_field',
'fields'=>array(
'name'=>array('type'=>'string','index'=>'analyzed'),
'sort_name'=>array('type'=>'string','index'=> 'not_analyzed')
)
)
using above mapping, you can search on name field and u can sort using sort_name.
{
'query': {
'query_string':{'query':'user_name*','fields':['name']}
},
'sort':[
{
'name.sort_name': {
'order': 'asc'
}
}
]
}
Reference Link :
1) http://awesomism.co.uk/536336#
2) http://blog.wiercinski.net/2011/uncategorized/elasticsearch-sorting-on-string-types-with-more-than-one-value-per-doc-or-more-than-one-token-per-field/

Related

ElasticSearch sorting based with wildcard in key

I have a data structure something like this from query. I want to apply a sort based on the date in the object values.
{
users: {
"1234": {
name: "User 1",
joining_date: "2022-12-28T11:37:00.000Z"
},
"3456": {
name: "User 2",
joining_date: "2022-12-18T11:37:00.000Z"
}
}
}
This is my query so far.
GET /_search
{
"sort" : [ {
"users.*.joining_date": {
"order": "desc",
"format": "date",
"unmapped_type": "long"
} }
],
"query": {
"query_string": {
"query": "_schema:users"
}
}
}
The problem is with using a wildcard in the key. I have tried multiple combinations from the documentation but nothing worked so far. I will be grateful for any help.

Searching upon multiple date fields in ElasticSearch

I have a document like this:
{
"listings": {
"mappings": {
"listing": {
"properties": {
"auctionOn": {
"type": "date"
},
"inspections": {
"type": "nested",
"properties": {
"endsOn": {
"type": "date"
},
"startsOn": {
"type": "date"
}
}
},
// more fields.. snipped for brevity
}
}
}
}
}
and i would like to perform the following search: (needs to be a bool filter.. no scoring req'd)
return documents any of the inspections.startsOn matches any of the dates provided (if they are provided)
OR
return documents where auctionOn matches the date provided (if it's provided)
they can also specify to search for a) inspections only, b) auctions only. if not provided, either of the dates need to match.
So in other words, possible searches:
Search where there are any inspections/auctions
Search where there are any inspections
Search where there are any auctions
Search where there are any inspections/auctions on the dates provided
Search where there are any inspections on the dates provided
Search where there are any auctions on the dates provided
Now, i'm already in a bool query filter:
{
"query":
{
"bool":
{
"filter":[{"terms":{"location.suburb":["Camden"]}}
}
}
}
and i need this new filter to be seperate. so.. this is like a nested or filter, within a main bool filter?
So if provided "Suburb = Camden, Dates = ['2018-11-01','2018-11-02']'
then it should return documents where the suburb = Camden and either the inspections or auction date includes one of the dates provided.
I'm kinda stumped on how to do it, so any help would be much appreciated!
There will lot of bool query combinations for the cases you mentioned in the question. Taking the example you mention i.e.
So if provided "Suburb = Camden, Dates = ['2018-11-01','2018-11-02']'
then it should return documents where the suburb = Camden and either
the inspections or auction date includes one of the dates provided.
Assuming your location filter is working as expected, for dates part in the above e.g. additions to the query will be:
{
"query": {
"bool": {
"filter": [
{
"terms": {
"location.suburb": [
"Camden"
]
}
},
{
"bool": {
"should": [
{
"terms": {
"auctionOn": [
"2018-11-01",
"2018-11-02"
]
}
},
{
"nested": {
"path": "inspections",
"query": {
"bool": {
"should": [
{
"terms": {
"inspections.startsOn": [
"2018-11-01",
"2018-11-02"
]
}
},
{
"terms": {
"inspections.endsOn": [
"2018-11-01",
"2018-11-02"
]
}
}
]
}
}
}
}
]
}
}
]
}
}
}

Search for documents with exactly different fields values

I'm adding documents with the following strutucte
{
"proposta": {
"matriculaIndicacao": 654321,
"filial": 100,
"cpf": "12345678901",
"idStatus": "3",
"status": "Reprovada",
"dadosPessoais": {
"nome": "John Five",
"dataNascimento": "1980-12-01",
"email": "fulanodasilva#fulano.com.br",
"emailValidado": true,
"telefoneCelular": "11 99876-9999",
"telefoneCelularValidado": true,
"telefoneResidencial": "11 2211-1122",
"idGenero": "1",
"genero": "M"
}
}
}
I'm trying to perform a search with multiple field values.
I can successfull search for a document with a specific cpf atribute with the following search
{
"query": {
"term" : {
"proposta.cpf" : "23798770823"
}
}
}
But now I need to add an AND clause, like
{
"query": {
"term" : {
"proposta.cpf" : "23798770823"
,"proposta.dadosPessoais.dataNascimento": "1980-12-01"
}
}
}
but it's returning an error message.
P.S: If possible I would like to perform a search where if the field doesn't exist, it returns the document that matches only the proposta.cpf field.
I really appreciate any help.
The idea is to combine your constraints within a bool/should query
{
"query": {
"bool": {
"should": [
{
"term": {
"proposta.cpf": "23798770823"
}
},
{
"term": {
"proposta.dadosPessoais.dataNascimento": "1980-12-01"
}
}
]
}
}
}

Return distinct values in Elasticsearch

I am trying to solve an issue where I have to get distinct result in the search.
{
"name" : "ABC",
"favorite_cars" : [ "ferrari","toyota" ]
}, {
"name" : "ABC",
"favorite_cars" : [ "ferrari","toyota" ]
}, {
"name" : "GEORGE",
"favorite_cars" : [ "honda","Hyundae" ]
}
When I perform a term query on favourite cars "ferrari". I get two results whose name is ABC. I simply want that the result returned should be one in this case. So my requirement will be if I can apply a distinct on name field to receive one 1 result.
Thanks
One way to achieve what you want is to use a terms aggregation on the name field and then a top_hits sub-aggregation with size 1, like this:
{
"size": 0,
"query": {
"term": {
"favorite_cars": "ferrari"
}
},
"aggs": {
"names": {
"terms": {
"field": "name"
},
"aggs": {
"single_result": {
"top_hits": {
"size": 1
}
}
}
}
}
}
That way, you'll get a single term ABC and then nested into it a single matching document

A simple AND query with Elasticsearch

I am trying to do a simple query for two specified fields, and the manual and google is proving to be of little help. Example below should make it pretty clear what I want to do.
{
"query": {
"and": {
"term": {
"name.family_name": "daniel",
"name.given_name": "tyrone"
}
}
}
}
As a bonus question, why does it find "Daniel Tyrone" with "daniel", but NOT if I search for "Daniel". It behaves like a realy weird anti case sensitive search.
Edit: Updated, sorry. You need a separate Term object for each field, inside of a Bool query:
{
"query": {
"bool": {
"must" : [
{
"term": {
"name.family_name": "daniel"
}
},
{
"term": {
"name.given_name": "tyrone"
}
}
]
}
}
}
Term queries are not analyzed by ElasticSearch, which makes them case sensitive. A Term query says to ES "look for this exact token inside your index, including case and punctuation".
If you want case insensitivity, you could add a keyword + lowercase filter to your analyzer. Alternatively, you could use a query that analyzes your text at query time (like a Match query)
Edit2: You could also use And or Bool filters too.
I found a solution for at least multiple text comparisons on the same field:
{
"query": {
"match": {
"name.given_name": {
"query": "daniel tyrone",
"operator": "and"
}
}
}
And I found this for multiple fields, is this the correct way?
{
"query": {
"bool": {
"must": [
{
"match": {
"name.formatted": {
"query": "daniel tyrone",
"operator": "and"
}
}
},
{
"match": {
"display_name": "tyrone"
}
}
]
}
}
}
If composing the json with PHP, these 2 examples worked for me.
$activeFilters is just a comma separated string like: 'attractions, limpopo'
$articles = Article::searchByQuery(array(
'match' => array(
'cf_categories' => array(
'query' => $activeFilters,
'operator' =>'and'
)
)
));
// The below code is also working 100%
// Using Query String https://www.elastic.co/guide/en/elasticsearch/reference/1.4/query-dsl-query-filter.html
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
/* $articles = Article::searchByQuery(array(
'query_string' => array(
'query' => 'cf_categories:attractions AND cf_categories:limpopo'
)
)); */
This worked for me: minimum_should_match is set to 2 since the number of parameters for the AND query are 2.
{
"query": {
"bool": {
"should": [
{"term": { "name.family_name": "daniel"}},
{"term": { "name.given_name": "tyrone" }}
],
"minimum_should_match" : 2
}
}
}

Resources