ElasticSearch _count and _search apply same query - elasticsearch

i'm trying get count of total results for paginator, but the problem is that _filter and _count have different arguments, for example:
_search:
'from' => $offset,
'size' => $limit,
'query' => [
'match_phrase' => $q,
]
_count:
'index' => $index,
'type' => $type,
'q' => $q,
I need apply match_phrase also inside _count, because when will keep there just q then count/number will don't be correct...but does _count accept match_phrase?
It's _count right way or must use different way? I was searching long hours, but found just this Elastic Search _search vs. _count syntax but it's saying nothing for me..

Related

Why is the max_score higher than the _score-sorted first hit's _score in Elasticsearch?

I have an Elasticsearch (8.1) index on which I run a simple match or multi_match query (I tried both, both show the same behavior, even the simplest ones).
In the result it is always the case that max_score is higher than the first hit's _score.
If I add a terms aggregation (on a keyword field) with a top_hits sub-aggregation (with sorting on _score) then the first hit from the first bucket actually has _score == max_score (but it is obviously also a different hit compared to the "main" hits). So, the top_hits aggregation actually does what I want ("fetch all matching documents and sort by _score"). The "main" hits seem to miss some results, however.
How can I make sure that the "main" hits do not "drop" documents? What is the internal mechanics behind this?
I added my PHP array that gets JSON encoded and produces the Elasticsearch query:
[
'size' => 10,
'query' => [
// the result of this does not have all documents
// that appear in the aggregation
// and the highest ranked doc has lower score than max_score
'bool' => [
'must' => [
[
'match' => [
'my_text_field' => [
'query' => 'searchword'
]
]
],
['term' => ['my_other_field' => ['value' => 3]]],
// plus some more other simple term conditions
// on other simple integral fields, but no scripts ore similar
// simple "WHERE a = 5" conditions
]
]
],
// this aggregation has other/more hits than the directly retrieved docs, matching the max_score
// If I remove the aggregation nothing changes for the actual result
'aggs' => [
'my_agg' => [
'terms' => ['field' => 'my_agg_field', 'order' => ['score' => 'desc']],
'aggs' => [
'score' => ['max' => ['script' => '_score']],
'filteredHits' => [
'top_hits' => [
'size' => 10
]
]
]
]
]
]

Query one field with multiple values in elasticsearch nest

I have a combination of two queries with Elasticsearch and nest, the first one is a full-text search for a specific term and the second one is to filter or query another field which is file-path but it should be for many files paths and the path could be part or full path, I can query one file-path but I couldn't manage to do it for many file paths, any suggestion?
Search<SearchResults>(s => s
.Query(q => q
.Match(m => m.Field(f => f.Description).Query("Search_term"))
&& q
.Prefix(t => t.Field(f => f.FilePath).Value("file_Path"))
)
);
For searching for more than one path you can use bool Query in elasticsearch and then use Should Occur to search like logical OR, so you code should look like this:
Search<SearchResults>(s => s
.Query(q => q.
Bool(b => b
.Should(
bs => bs.Wildcard(p => p.FilePath, "*file_Pathfile_Path*"),
bs => bs.Wildcard(p => p.FilePath, "*file_Pathfile_Path*"),
....
))
&& q.Match(m => m.Field(f => f.description).Query("Search_term")
)));
Also you should use WildCard Query to get result for paths that could be part or full path. For more information check ES offical documentation about WildQuery and Bool Query below:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html

Elasticsearch aggregations: strategy for accessing additional fields

I am using the following code for aggregations. It only return the Id and I would also like to return the Name. We did a project a few years ago and we indexed a field called idName (separated by |) but it was so messy solution. I am wondering if there are any better ways to do this with the recent version of Elastic?
.Aggregations(aggs => aggs
.Nested("nested_cat", nested => nested
.Path(p => p.Categories)
.Aggregations(a1 => a1
.Terms("terms_cat_id", terms1 => terms1
.Field(f1 => f1.Categories.First().Id)
)
)
)
)
I read there are 2 other options. One is to do a sub-aggregation, however the following doesn't seem to work:
.Aggregations(aggs => aggs
.Nested("nested_cat", nested => nested
.Path(p => p.Categories)
.Aggregations(a1 => a1
.Terms("terms_cat_id", terms1 => terms1
.Field(f1 => f1.Categories.First().Id)
.Aggregations(a2 => a2
.Terms("terms_cat_name", terms2 => terms2
.Field(f2 => f2.Categories.First().Name)
)
)
)
)
)
)
I also read that I can use Scripts, but I haven't gotten that to work either.
I was able to get the sub-aggregation to work by mapping category.name as "Keyword" instead of "Text"

ElasticSearch NEST custom word joiner Analyzer not returning the correct result

I created an autocomplete filter with ElasticSearch using NEST API. I cant seem to get the word joiner to work.
So basically if I search for something like Transhex i also want to be able to return Trans Hex
My Index looks as follow...I think the WordDelimiter filter might be wrong.
Also, I followed the following article Link. They use the low-level API so it is possible that I am doing it completely wrong using the NEST API
var response = this.Client.CreateIndex(
"company-index",
index => index.Mappings(
ms => ms.Map<CompanyDocument>(m => m.Properties(p => p
.Text(t => t.Name(n => n.CompanyName).Analyzer("auto-complete")
.Fields(ff => ff.Keyword(k => k.Name("keyword")))))))
.Settings(f => f.Analysis(
analysis => analysis
.Analyzers(analyzers => analyzers
.Custom("auto-complete", a => a.Tokenizer("standard").Filters("lowercase", "word-joiner-filter", "auto-complete-filter")))
.TokenFilters(tokenFilter => tokenFilter
.WordDelimiter("word-joiner-filter", t => t.CatenateAll())
.EdgeNGram("auto-complete-filter", t => t.MinGram(3).MaxGram(30))))));
UPDATE
So I updated the Analyzer to look as follows, noticed that I updated the Analyzer from standard to keyword.
var response = this.Client.CreateIndex(
this.indexName,
index => index.Mappings(
ms => ms.Map<CompanyDocument>(m => m.Properties(p => p
.Text(t => t.Name(n => n.CompanyName).Analyzer("auto-complete")
.Fields(ff => ff.Keyword(k => k.Name("keyword")))))))
.Settings(f => f.Analysis(
analysis => analysis
.Analyzers(analyzers => analyzers
.Custom("auto-complete", a => a.Tokenizer("keyword").Filters("lowercase", "word-joiner-filter", "auto-complete-filter")))
.TokenFilters(tokenFilter => tokenFilter
.WordDelimiter("word-joiner-filter", t => t.CatenateAll())
.EdgeNGram("auto-complete-filter", t => t.MinGram(1).MaxGram(20))))));
The Results will look as follows
Search Keyword : perfect pools
Results
perfect pools -> This is the correct one at the top
EXCLUSIVE POOLS
Perfect Painters
Search Keyword : perfectpools Or PerfectPools
Results
Perfect Hideaways (Pty) Ltd -> this is the wrong one i would like to display perfect pools
PERFORMANTA APAC PTY LTD
Perfect Laser Technologies (PTY) LTD
Use Keyword tokenizer. The standard tokenizer will split the word in 2 tokens, then apply the filters on them.
UPDATE:
I used a search like this one and seems ok.
var searchResult = EsClient.Search<CompanyDocument>(q => q
.Index("test_index")
.Type("companydocument")
.TrackScores(true)
.Query(qq =>
{
QueryContainer queryContainer = null;
queryContainer = qq.QueryString(qs => qs.Fields(fs => fs.Field(f => f.CompanyName)).Query("perfectpools").DefaultOperator(Operator.And).Analyzer("auto-complete"));
return queryContainer;
})
.Sort(sort => sort.Descending(SortSpecialField.Score))
.Take(10)
);

elasticsearch regroup aggs by prefix

Hi i make a search facets with elasticsearch so i use aggs to get this facets but i would like to regroup all term start with text until the first '/'
Example some value are indexing like 'levelone/leveltwo'
but i would like to regroup all same levelone value
i try that but it does not work
'aggs' = array( 'tags => array ('terms' => array (
'field' => $filter,
'size' => 0,
'include' => ".*/.*",
)
)
)
Is it possible ?

Resources