Search multiple indices against some index pattern using NEST - elasticsearch

I searched NEST docs but seems to cant find a proper answer for it.
My question is how to search multiple indices against some index pattern using NEST? e.g
if I have indices with following names in Elasticsearch DB
media-2017-10, media-2018-03, media-2018-04
For specifying my selected indices, I need to use wild card character * like this:
client.Search<Media>(s => s
.Index("media-*")
. query goes here .....
Is it possible in NEST ?

Yes, this works. Try it :)
.Index(...) accepts wildcard indices

You can also search in multiple indices in that way:
var allIndices = new[] {
"media-*",
"docs-*",
"common-*"
};
Nest.Indices allIndices = allIndices;
return _elasticClient
.SearchAsync<EsBaseModel>(s => s
.Index( allIndices)
.Size(_esConfig.MaxCallIDsSize)
.RequestConfiguration(r => r.RequestTimeout(TimeSpan.FromMinutes(5)))
.Query(q =>
q.Match(m => m.Field("fieldname").Query(condition))
));
Steps:
Just create an array with string indices.
Indices can be explicit or implicit using any pattern supported in Nest client docs.
Notice - neet to put attention to optimize the searching, since it could take a while to search in all the indices that you've provided.
(optimize can be achieved by ignoring very old dates, limit the results, etc...)

Related

Elasticsearch: Limit of total fields setting when creating index

I am struggling with a new problem in ElasticSearch 7. I get the "limit of total fields" error when trying to create the index with auto map in Nest library, c#.
await _elasticContext.GetClient().Indices.CreateAsync(indexName, c => c
.Map<DocumentWrapper>(m => m.AutoMap()));
Question is how to integrate the index.mapping.total_fields.limit into the query above? Or an alternative solution, if there is one?
Thank you
Please find an example below
var response = await client.Indices.CreateAsync("my_index1", c => c
.Settings(s => s.Setting("index.mapping.total_fields.limit", 10))
.Map(m => m.AutoMap<Document>()));
Hope that helps.
The maximum number of fields in an index. Field and object mappings, as well as field aliases count towards this limit. The default value is 1000.
see doc

Elasticsearch - with or without a "doc."?

I'm facing some strange issue with "doc." keyword on Nest C# Elasticsearch.
I'm using Couchbase, and I have a class where one of its fields is an array of objects
I try to search inside this array for a specific value.
Something like this:
string mailFilesKey = string.Empty;
ISearchResponse<object> result = _mainManager.Client.Search<object>(c => c
.Type("MailFiles")
.Query(q =>
q.Term("SentFile_Id", fileId))
.Size(1));
Now, this thing actually works. But when I do this one, it doesn't work:
q.Term("doc.SentFile_Id", fileId))
Why?
haha ok nice one. I had this thing long time ago when i started to use Nest and elastic. If you have the object then you can use lambda expressions
like f=>f.SentFile_Id.
Now when you use a string to get the name of the field in nest you must know that all fields, index name, types in elastic are stored with lowercase first letter. So you should use this : q.Term("sentFile_Id", fileId))
Should work just fine.

Create NEST search request for Elasticsearch with ignore_unavailable set to true?

I want to create a NEST search request for elasticsearch and ignore index not exists errors. I can do this using sense by appending ?ignore_unavailable=true to the search request but can't find a way to set this with NEST.
This should do what you want:
var searchResult = this._client.Search<ElasticsearchProject>(s => s
.IgnoreUnavailable()
.MatchAll()
);

how to merge elasticsearch results into one field or how to explain which field results were found in

follow me on this one...
if i've got a db of movies and i want to search on multiple fields and return the results into a single field, how would i accomplish this?
let me set an example...
my documents have a title and artists.name (array). i want the user to be able to search in both title and artist at the same time so that the results are in the same field. this would be implemented in an 'autocomplete' search scenario where you get results as you type.
so if a user types 'mike' i want to be able to search for actors (artists.name) with the name mike and titles with the word mike in it. in this case, you might return 'magic mike' and 'mike meyers' in the same autocomplete result set. (imdb.com has this implementation)
i understand how to search both of those fields, but how do i return them into one? i believe i'd have to have some knowledge on where my 'hit' came from - title or artists.name. so maybe that's the larger question here - how do i tell which field the hit came from?
I don't think there are any direct ways to determine which field(s) a query matched on. I can think of a few "workaround" approaches that may do it for you- one is by using the multisearch api, and executing separate queries on each field. Another is using highlighting, which will return back the fields that a match was found in.
Example using multi search:
var response = client.MultiSearch(ms => ms
.Search<Artist>("name", s => s.Query(q => q.Match(m => m.OnField(a => a.Name).Query("mike"))))
.Search<Artist>("titles", s => s.Query(q => q.Match(m => m.OnField(a => a.Titles).Query("mike")))));
response.GetResponse<Artist>("name"); // <-- Contains search results from matching on Name
response.GetResponse<Artist>("titles"); // <-- Contains search results from matching on Titles
Example using highlighting:
var response = client.Search<Artist>(s => s
.Query(q => q
.MultiMatch(m => m
.OnFields(a => a.Name, a => a.Titles)
.Query("mike")))
.Highlight(h => h
.OnFields(fs => fs.OnField(a => a.Name),
fs => fs.OnField(a => a.Titles))));
You can then inspect the Highlights object of each hit, or the Highlights object of the response to determine what field the match came from.
There is also the explain api, and you can add explain to your query, but that will return a lot of irrelevant scoring info, which you would have to parse through. Probably too cumbersome for your needs.
As a side note- for autocomplete functionality, if possible I would really try to leverage the completion suggester instead of the above solutions. These are pre-computed suggestions that are created when you index your documents by building up FSTs, which will increase your indexing time as well as index size, but as a result will provide extremely fast suggestions.

Elasticsearch Nest not honoring index = not_indexed on POCO field?

i just found out through the documentation that we should be telling it to use the mapping attributes and manually creating the index before we index.
however, the documentation is not consistent with the newest version of the code. (pre release).
http://nest.azurewebsites.net/nest/indices/put-mapping.html
var response = this.ConnectedClient.Map<ElasticSearchProject>();
the call above in the new code takes 1 argument in the Map() method. the documentation is not requiring any arguments.
what should be contained in that method? it seems like there are many options, but i'm unclear on which ones to use.
Have a look at the Create Indices documentation. I think something like this will work for what you are trying to accomplish. Plus it will create the index and apply the mapping all in one call to your Elasticsearch instance.
client.CreateIndex("myindexname", c => c
.NumberOfReplicas(0)
.NumberOfShards(1)
.Settings(s=>s
.Add("merge.policy.merge_factor","10")
.Add("search.slowlog.threshold.fetch.warn", "1s")
)
.AddMapping<ElasticSearchProject>(m => m.MapFromAttributes())
.AddMapping<Person>(m => m.MapFromAttributes())
);
The .AddMapping<ElasticSearchProject>(m => m.MapFromAttributes()) line tells NEST to grab all of the Attribute settings on the via ElasticType and ElasticProperty on the ElasticSearchProject class and use those to create the mapping.

Resources