How to order by date documents in aggregator with elasticsearch - elasticsearch

I have this aggregators to deduplicate documents :
$searchParams['body'] = [
'aggs' => [
'dedup' => [
'terms' => [
'field' => 'source',
'size' => 50,
'order' => [
'max_hits' => "desc"
]
],
'aggs' => [
'dedup_hits' => [
'top_hits' => [
'size' => 1
]
],
'max_hits' => [
'max' => [
"script" => "doc.score"
]
]
]
]
]
];
This query order by document score. However, i want to order by _timestamp field. It's possible ? I have test with Date Histogram aggregator. But without success.

Related

How to include mapped fields subfield in result in Elasticsearch?

For aggregation, I have a raw value of my field. But I can't access this value in my query. For example, in my case I have a brand Tommy Hilfiger and it's raw value tommy-hilfiger as a brand.keyword. How to include this value in a search results?
'body' => [
'settings' => [
'analysis' => [
'filter' => [
'remove_spaces_inside' => [
'type' => 'pattern_replace',
'pattern' => '\\s+',
'replacement' => ' '
],
'convert_spaces' => [
'type' => 'pattern_replace',
'pattern' => '\\s+',
'replacement' => '-'
],
],
'char_filter' => [
'convert_amp' => [
'type' => 'pattern_replace',
'pattern' => '&',
'replacement' => 'and'
]
],
'analyzer' => [
'slug' => [
'char_filter' => ['convert_amp'],
'tokenizer' => 'keyword',
'filter' => ['trim', 'lowercase', 'asciifolding', 'remove_spaces_inside', 'convert_spaces']
],
'format' => [
'char_filter' => ['convert_amp'],
'tokenizer' => 'keyword',
'filter' => ['trim', 'remove_spaces_inside']
]
]
]
],
'mappings' => [
'my_type' => [
'properties' => [
'brand' => [
'type' => 'string',
'fields' => [
'keyword' => [
'type' => 'string',
'analyzer' => 'slug',
'index_options' => 'docs',
]
]
]
]
]
]
]
Upd.
In my case, I store brand in 2 fields: default "Tommy Hilfiger" for full-text search, formatted keyword (slug) "tommy-hilfiger" for exact search. I can aggregate data by slug, but can't get this field in my query. For example, this query return all records with brand Tommy Hilfiger, but only default values, not a slug.
'body' => [
'_source' => [
'brand',
'brand.keyword'
],
'query' => [
'bool' => [
'must' => [
[
'terms' => [
'brand.keyword' => [
'tommy-hilfiger',
]
]
]
]
]
]
]

Elasticsearch syntax error with multi fields search

I watched Elasticsearch Do's, Don'ts and Pro-Tips by Itamar Syn Hershko
https://www.youtube.com/watch?v=c9O5_a50aOQ
I see multiple conditions in several fields in the following image:
https://imgur.com/a/17zAZ4w
I tried to make it in
my Laravel 5.7 app (with the elasticsearch/elasticsearch plugin) as seen in the following code:
$elasticQuery = [
"bool" => [
'must' => [
'multi_match' => [
'query' => $text,
'fields' => ['name^4', 'description']
],
],
"should" => [
'term' => [
"category_id" => 1,
]
]
]
];
but I got the error :
{"error":{"root_cause":[{"type":"parsing_exception","reason":"[bool] malformed query, expected [END_OBJECT] but found [FIELD_NAME]","line":1,"col":130}],"type":"parsing_exception","reason":"[bool] malformed query, expected [END_OBJECT] but found [FIELD_NAME]","line":1,"col":130},"status":400}
But when I use a simple condition:
$elasticQuery = [
'multi_match' => [
'query' => $text,
'fields' => ['name^4', 'description'],
],
];
I got a valid result:
[hits] => Array
(
[total] => 1
[max_score] => 7.4126062
[hits] => Array
(
[0] => Array
(
[_index] => select_vote
[_type] => vote
[_id] => 16
[_score] => 7.4126062
[_source] => Array
(
[id] => 16
[slug] => in-the-film-babe-what-type-of-animal-was-babe
[name] => In the film Babe, what type of animal was Babe?
[description] => Babe is a 1995 A...
[created_at] => 2018-11-10 09:14:15
[category_id] => 2
[category] => Array
(
[name] => Movie&Cartoons
[slug] => movie-cartoons
[created_at] => 2018-11-10 09:14:12
)
)
)
)
)
is this a valid format for multi-request?
MODIFIED BLOCK # 2:
Making some search I found work:
$elasticQuery = [
"bool" => [
'should' => [
[
"multi_match" => [
"query" => $text,
"type" => "cross_fields",
"fields" => [
"name^4",
"description"
]
]
],
[
'match' => [
'category_id' => [
'query' => 1,
]
]
],
[
'match' => [
'category_id' => [
'query' => 3,
]
]
],
]
]
];
when I need to make a search by text fields and the array of category (1 and 3) in the example above it works but looks like it works like an "OR" condition, but I need to make a restriction like "AND" using SQL terminology...
Which way is correct in order to make a restriction as like "AND"?
Thanks!
If you just change should to must it is not going to work because category_id cannot have two values at the same time (unless it's an array, but it's not).
You need to use the following query instead:
$elasticQuery = [
"bool" => [
'must' => [
[
"multi_match" => [
"query" => $text,
"type" => "cross_fields",
"fields" => [
"name^4",
"description"
]
]
],
],
'filter' => [
[
'terms' => [
'category_id' => [ 1, 3 ]
]
]
]
]
];

Calculate Average of an Array's indexes in ElasticSearch

I am trying to calculate average of the result set that is returning me locations from Elastic Search. Here is what i am trying.
'aggs' => [
"avg_location" => [
'avg' => [
'field' => 'location'
]
]
]
This returns error as location itself is an object/array that returns me [lat,long] of the point. I need to calculate average of lats and longs of all the points returned.
How can i do that? I tried quite a few things but none of them worked.
Here is the whole code.
$json = [
'query' => [
'bool' => [
'must_not' => [
'terms' => ['rarity' => []],
],
'must' => [
'range' => [
'disappearTime' => [
'gte' => 'now',
'lte' => 'now+1d'
]
]
],
'filter' => [
[
'geo_bounding_box' => [
'location' => [
'top_left' => [
'lat' => $northWestLat,
'lon' => $northWestLng
],
'bottom_right' => [
'lat' => $southEastLat,
'lon' => $southEastLng
]
]
]
]
]
]
],
'aggs' => [
"avg_location" => [
'avg' => [
'field' => 'location'
]
]
]
];
Thanks

Elastic search to match top level field, and a nested field

I can't seem to get this query to work
I am trying to match all tags who's name matches $channel_name,
but also, which has a video, with the name of $search.
I think the nested part is messed up. How can I fix this query?
$body = [
'query' =
[
"bool" => [
"must" => [
'match_phrase' => ['name' => $channel_name]
],
'nested' => [
'path' => 'videos',
'query' => [
'bool' => [
[
'must' => [
'match' => [
'videos.name' => $search
]
]
]
]
]
]
],
],
'inner_hits' => [
'videos' => [
'path' => [
'videos' => [
'size' => $this->pageSize,
'sort' => $sortOrder,
'from' => ($pageNumber - 1) * $this->pageSize,
'query' => [
'match_all' => []
]
]
]
]
]
];

Elasticsearch query for simple category search, sorting by price and getting records by range

I want to write query with following condition :
search by category (like category = 'cat1')
and with price range (and price between 100 to 500)
and sort by price (low to high)
I tried:
$params = [
'index' => 'my_index',
'type' => 'product',
'body' => [
//"from" => 0, "size" => 2,
"sort" => [
["default_product_low_price.sale_price" => ["order" => "asc"]]
],
'query'=> $query,
"aggs" => [
"default_product_low_price" => [
"nested" => [
"path" => "default_product_low_price"
],
"aggs" => [
"range" => ["default_product_low_price.sale_price" => [ "gte" => '790',
"lte" => '1000' ]],
//"max_price" => ["max" => [ "field" => "default_product_low_price.sale_price" ]]
],
]
]
]
];
But I am getting an error
Bad Request 400 Exception in GuzzleConnection.php line 277: error.
Please guide me where I am wrong? What is the right query?
I think this should be your query :
$params = [
'index' => 'my_index',
'type' => 'product',
'body' => [
"sort" =>[
["default_product_low_price.sale_price" => ["order" => "asc"]]
],
"query"=> [
"filtered"=> [
"query"=> [
"match_all"=> []
],
"query"=>[
"term"=> [
"category.name"=> "jeans"
]
],
"filter"=> [
"nested"=> [
"path"=> "default_product_low_price",
"filter"=> [
"bool"=> [
"must"=> [
[
"range"=> [
"default_product_low_price.sale_price"=> [
"gte"=> 100,
"lte"=> 200,
]
]
]
]
]
]
]
]
]
]
]
];

Resources