Elasticsearch NEST API, Searching Multiple Indices - elasticsearch

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

Related

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

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())
)
);

Is it possible to query aggregations on NEST for multiple term fields (.NET)?

Below is the NEST query and aggregations:
Func<QueryContainerDescriptor<ConferenceWrapper>, QueryContainer> query =
q =>
q.Term(p => p.type, "conference")
// && q.Term(p => p.conference.isWaitingAreaCall, true)
&& q.Range(d => d.Field("conference.lengthSeconds").GreaterThanOrEquals(minSeconds))
&& q.DateRange(qd => qd.Field("conference.firstCallerStart").GreaterThanOrEquals(from.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")))
&& q.DateRange(qd => qd.Field("conference.firstCallerStart").LessThanOrEquals(to.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")));
Func<AggregationContainerDescriptor<ConferenceWrapper>, IAggregationContainer> waitingArea =
a => a
.Terms("both", t => t
.Field(p => p.conference.orgNetworkId) // seems ignore this field
.Field(p => p.conference.isWaitingAreaCall)
// .Field(new Field( p => p.conference.orgNetworkId + "-ggg-" + p.conference.networkId)
.Size(300)
.Aggregations(a2 => a2.Sum("sum-length", d2 => d2.Field("conference.lengthSeconds"))));
I have called .Field(p => p.conference.orgNetworkId) followed by .Field(p => p.conference.isWaitingAreaCall) But it seems the NEST client tries to ignore the first field expression.
Is is possible to have multiple fields to be the terms group by?
Elasticsearch doesn't support a terms aggregation on multiple fields directly; the calls to .Field(...) within NEST are assignative rather than additive, so the last call will overwrite any previously set values.
In order to aggregate on multiple fields, you can either
Create a composite field at index time that incorporates the values that you wish to aggregate on
or
Use a Script to generate the terms on which to aggregate at query time, by combining the two field values.
The performance of the first option will be better than the second.

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

how do i set similarity in nest for elasticsearch on a per field basis

i have not been able to 'programmatically' set the similarity on a field in elasticsearch using Nest.
here's an example of how i set up my index. it's within the multifield mapping where i'd like to set the similarity so i can experiment with things like BM25 similarity...
(see the props > multifield section below)...
var createInd = client.CreateIndex("myindex", i =>
{
i
.Analysis(a => a.Analyzers(an => an
.Add("nameAnalyzer", nameAnalyzer)
)
.AddMapping<SearchData>(m => m
.MapFromAttributes()
.Properties(props =>
{
props
.MultiField(mf => mf
//title
.Name(s => s.Title)
.Fields(f => f
.String(s => s.Name(o => o.Title).Analyzer("nameAnalyzer"))
.String(s => s.Name(o => o.Title.Suffix("raw")).Index(FieldIndexOption.not_analyzed))
)
);
...
It was just recently made possible with this commit to set the similarity on a string field. You can now do this:
.String(s => s.Name(o => o.Title).Similarity("my_similarity")
This is assumming you already have the similarity added to your index. NEST is lacking a bit of flexibility at the moment for actually configuring similarities. Right now you have to use the CustomSimilaritySettings class. For example:
var bm25 = new CustomSimilaritySettings("my_similarity", "BM25");
bm25.SimilarityParameters.Add("k1", "2.0");
bm25.SimilarityParameters.Add("b", "0.75");
var settings = new IndexSettings();
settings.Similarity = new SimilaritySettings();
settings.Similarity.CustomSimilarities.Add(bm25);
client.CreateIndex("myindex", c => c.InitializeUsing(settings));
It would be nice to be able to do this via the fluent API when creating an index. I am considering sending a PR for this before the 1.0RC release.

Resources