How can I find the total hits for an Elastic NEST query? - elasticsearch

In my application I have a query which brings limits the number of hits returned to 50 as follows
var response = await client.SearchAsync<Episode>(s => s
.Source(sf => sf
.Includes(i => i
.Fields(
f => f.Title,
f => f.PublishDate,
f => f.PodcastTitle
)
)
.Excludes(e => e
.Fields(f => f.Description)
)
)
.From(request.Skip)
.Size(50)
.Query(q => q
.Term(t => t.Title, request.Search) || q
.Match(mq => mq.Field(f => f.Description).Query(request.Search))));
I am interested in the total number of hits for the query (i.e. not limited to the size), so that I can deal with pagination on the front-end. Does anyone know how I can do this?

You are looking for Total property on the search response object. Have a look.
So in your particular case that will be response.Total.

For those who are working on indices with more than 10000 documents, Elasticsearch will calculate total hits up to 10000 by default. To get around that, include .TrackTotalHits(true) in your query:
var resp = client.Search<yourmodel>(s => s
.Index(yourindexname)
.TrackTotalHits(true)
.Query(q => q.MatchAll()));

Related

Elasticsearch NEST API, Searching Multiple Indices

If one is seraching several indexes at the same time, is there any way to say that if searching index A, then add this filter and if searching index B then add a different filter.
For example:
var filters = new List<Func<QueryContainerDescriptor<PropertySearchResult>, QueryContainer>>();
filters.Add(fq => fq.Term(t => t.Field(f => f.PromoterId).Value(user.Id)));
filters.Add(fq => fq.Term(t => t.Field(f => f.SubscriptionId).Value(subscriptionId)));
string indicies = String.Join(",", Utils.SupportedCountries.Select(c => c.Key.ToLower()).ToArray());
var result = await ElasticSearchConfig.GetClient().DeleteByQueryAsync<PropertySearchResult>(u => u
.Index(indicies)
.Query(q => q
.Bool(bq => bq.Filter(filters))));
at the moment, all indices will be subject to the same filters but I would like to vary the filters based on which index is being searched.
Add(with &&) a term query to each of your filters
.Term("_index", A)
Check this link
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-index-field.html

How to construct Aggregation (Count) of records using NEST?

I have a requirement to perform Aggregation (Count) of records using NEST wrapper but to fire the DSL query inside NEST.
Since I don't know how to construct it properly, I have done the same using LINQ approach.
ISearchResponse<AgencyDetailReportModel> searchResponse = ConnectionToESClient().Search<AgencyDetailReportModel>
(s => s
.Index("accountsdata")
.From(0)
.Size(15000)
.Query(q =>
q.MatchAll()
)
);
var allocatedAgencies = agencySearchResponse.Documents.Where(w => !string.IsNullOrEmpty(w.agencyid)).Count();
var unAllocatedAgencies = agencySearchResponse.Documents.Where(w => string.IsNullOrEmpty(w.agencyid)).Count();
How can I construct the DSL query inside NEST?
So for your question you need allocatedAgencies count and unAllocatedAgencies count right.We can achieve this by simple query rather than going for aggregations.
var searchResponse = await highLevelClient.CountAsync<accountsdata>(s => s
.Index("accountsdata")
.Query(q => q
.ConstantScore(c => c
.Filter(f => f
.Bool(b => b
.MustNot(m => m
.Exists(e => e.Field("agencyid"))))))));
This is for unAllocatedAgencies count and for allocatedAgencies below is the query.
var searchResponse = await highLevelClient.CountAsync<accountsdata>(s => s
.Index("accountsdata")
.Query(q => q
.ConstantScore(c => c
.Filter(f => f
.Bool(b => b
.Must(m => m
.Exists(e => e.Field("agencyid"))))))));
Let me know if you face any issues, max it will work for your above mentioned problem. Thanks

Using which field matched in a multimatch query in a function score

I have a multimatch query which I am using across 5 fields. I am also using a function score to combine various factors into the score. I would like to add a factor to this so that results that matched on one of the fields is increased (adding a large number so that matches on this field always have the highest score).
I know that I can use highlighting to find out which fields were matched, but how can I access that information in the function score script?
Here's what I have so far (using NEST, but that shouldn't make a difference).
var searchResponse = client.Search<TopicCollection.Topic>(s => s
.Query(q => q
.FunctionScore(fs => fs
.Name("function_score_query")
.Query(q1 => q1
.MultiMatch(c => c
.Fields(f => f
.Field(p => p.field1)
.Field(p => p.field2) //...etc
.Query(searchTerm)
)
)
.Functions(fun => fun
.ScriptScore(ss => ss.Script(sc => sc
.Inline(
//TODO: add 1000 to normalised _score if match is in field1
)))
).BoostMode(FunctionBoostMode.Replace)
)
).Highlight(h => h
.Fields(p => p.AllField())
)
);

Number of records in index

I have an elasticsearch query method, but it only yields me 10 records of an index --- does someone know how I can get all the records that I have?
var consultaPlazaCobro = elasticClient.Search<Entity.PlazaCobroELK>(s => s
.Index("plazacobro")
.Type("logs")
.Query(q => q.QueryString(qs => qs.Query("*"))));
If you have less than 10000 documents, you can use the .Size() method call:
var consultaPlazaCobro = elasticClient.Search<Entity.PlazaCobroELK>(s => s
.Size(10000)
.Index("plazacobro")
.Type("logs")
.Query(q => q.QueryString(qs => qs.Query("*"))));
Otherwise you need to resort to using a Scroll request

Querying NEST 2.0.0-rc1 Aggregation Buckets

Previously in NEST (for Elasticsearch 1.x), after an aggregation query, I had some code that went through and grouped up aggregations by going through all the buckets, similar to this:
var r = (from SingleBucket items1 in result.Aggregation.Values
select (Bucket) agg1
into items1Aggs
from col1 in items1Aggs.Items.Cast<KeyItem>()
....
select new x {}).ToList();
But it seems that now the SingleBucket has to be SingleBucketAggregate, but the Bucketclass used before is now an internal BucketAggregateData class that is no long accessible. Is there any way around this?
Aggregation query being used:
var result = _client.Search<MetaStoreEntry>(s => s
.Aggregations(a => a
.Filter("fullGroupBy", k => fad
.Aggregations(e => e
.Terms("col1", t => t
.Field(f => f.col1)
.Aggregations(b => b
.Terms("col2", u => u
.Field(f => f.col2)
...
).Size(int.MaxValue).CollectMode(TermsAggregationCollectMode.DepthFirst)
) ...
);

Resources