Elastic search 2.0 GreaterOrEquals NEST 2.0 - elasticsearch

I use this code to search with date in elastic search 1.0. But this does not work in 2.0
var dateQuery = Query<SchoolModel>.Bool(
q => q.Should(p=>p.Range(r => r.OnField(f => f.schoolenddate).GreaterOrEquals(dateTime)))))
How can I convert this to elastic search 2.0

Sytanx in Nest 2.0
DateRange(c => c
.Field(p => p.schoolenddate)
.GreaterThanOrEquals(dateTime)
)
Link to docs
Latest version of elasticsearch is 7.*. So if you are upgrading better to get latest version

Related

What is the best way to save elastic search results to apply paging, sorting, filtering on top of results

I am using Elastic Search 6.7 with Nest in .net 6.0 and getting results on particular search. I am looking for a best technique to save these results so that I can apply paging, sorting and filtering on top of these results. I may get 50 to 500 documents in search results.
Currently each of my paging, sorting and filtering request go back to elastic search to get the results using this code :
var initialResponse = await _elasticClient.SearchAsync<TResult>
(scr => scr
.From(from)
.Size(pageSize)
.Preference(prefParam)
.Source(s => sourceSelector != null ? sourceSelector.Invoke(s) : query.GetSource() ?? s.IncludeAll())
.Query(q => query.GetQuery())
.PostFilter(p => query.GetPostFilter())
.ScriptFields(s => query.GetScriptedFields())
.MinScore(query.MinimumScore)
.Sort(s => query.GetSort() ?? new SortDescriptor<TResult>())
);
Can someone guide me properly with most efficient way where I can fetch results first time and apply operations on top of result set?
Thank you!

Creating an Index with English Analyzer using Nest

I am using nest to create my Elasticsearch Index. I have two questions:
Question 1. How can I add the settings to use english analyzer with a fall back for Standard Analyzer?
This is how I am creating my Index:
Uri _node = new Uri("elasticUri");
ConnectionSettings _connectionSettings = new ConnectionSettings(_node)
.DefaultIndex("MyIndexName")
.DefaultMappingFor<POCO>(m => m
.IndexName("MyIndexName")
);
IElasticClient _elasticClient = new ElasticClient(_connectionSettings);
var createIndexResponse = _elasticClient.CreateIndex("MyIndexName", c => c
.Mappings(m => m
.Map<POCO>(d => d.AutoMap())
)
);
Looking at the examples Here, I am also not sure what should I pass for "english_keywords", "english_stemmer", etc
Question 2: If I use English Analyzer, will Elasticsearch automatically realize that the terms: "Barbecue" and "BBQ" are synonyms? Or do I need to explicitly pass a list of Synonyms to ES?
Take a look at the NEST documentation for configuring a built-in analyzer for an index.
The documentation for the english analyzer simply demonstrates how you could reimplement the english analyzer yourself, as a custom analyzer, with the built-in analysis components, if you need to customize any part of the analysis. If you don't need to do this, simply use english as the name for the analyzer for a field
client.CreateIndex("my_index", c => c
.Mappings(m => m
.Map<POCO>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.MyProperty)
.Analyzer("english")
)
)
)
)
);
Will use the built-in english analyzer for the MyProperty field on POCO.
The english analyzer will not perform automatic synonym expansion for you, you'll need to configure the synonyms that are relevant to your search problem. You have two choices with regards to synonyms
Perform synonym expansion at index time on the index input. This will result in faster search at the expense of being a relatively fixed approach.
Perform synonym expansion at query time on the query input. This will result in slower search, but affords the flexibility to more easily add new synonym mappings as and when you need to.
You can always take the approach of using both, that is, indexing the synonyms that you expect to be relevant to your search use case, and adding new synonyms at query time, as you discover them to be relevant to your use case.

Elasticsearch and NEST: Filtering with Lookups

I'm using Elasticsearch 1.7.x (and NEST 1.7.2) and trying to take advantage of filtering with lookups as documented here: Terms Filter Lookup. I'm able to craft the JSON by hand for the request I desire and execute it using Sense. Works great, awesome feature! However, in the NEST library, I don't see a way to create such a terms clause. For example, from the link referenced above, I can do something like:
"terms" : {
"proteins" : {
"index" : "microarrays",
"type" : "experiment",
"id" : "experiment1234",
"path" : "upregulated_proteins"
},
"_cache_key" : "experiment_1234"
}
Is there a way to build this query using NEST? If not, is there a way I can inject some JSON into a NEST query as I'm building it? I don't know if NEST 2.x+ supports this but upgrading to ES 2.x is a longer term plan for us and I'd like to leverage functionality that is already available in ES 1.7.
Awesome, I've already received an answer from Greg Marzouka of Elastic! He says:
It's mapped as TermsLookup() or TermsLookupFilter in 1.x. Check out the unit tests for some examples.
client.Search<Paper>(s => s
.Query(q => q
.Filtered(fq => qf
.Filter(f => f
.CacheKey("experiment_1234")
.TermsLookup(t => t
.Lookup<Protein>(p => p.UnregulatedProteins, "experiment1234", "microarrays", "experiment")
)
)
)
));
In 2.x it's a little more aligned with the ES query DSL.

ElasticSearch Terms no longer working since upgrading to ES 2.x

Previously with ES 1.x I could construct my nest query like this:
Nest.SearchDescriptor<object> query = new Nest.SearchDescriptor<object>()
.Type("my_type")
.Size(Int16.MaxValue)
.Query(q => q.Terms("my_ID", my_list));
Since upgrading Nest (and ES to 2.3.0) though Terms no longer takes 2 parameters, so I figured this is the new way to do it:
Nest.SearchDescriptor<object> query = new Nest.SearchDescriptor<object>()
.Type("my_type")
.Size(Int16.MaxValue)
.Query(q => q.Terms(t => t.Name("my_ID").Terms(my_list)));
If I look at the json this produces now I see it's just this:
{ "size": 32767 }
What am I doing wrong?

how to add a full phrase tokenizer in Nest for Elasticsearch?

when i create a search using facets, i want the facet results to be on the whole phrase, not the individual word. and i want it NOT to be case sensitive - as 'not_analyzed' would do.
for example, if i have a music json object and want to organize the facet results based on genre, i want to see each genre as the whole genre term (rhythm and blues) and not one facet for 'rhythm' and one for 'blues', and i want to be able to search on 'rhythm and blues' and have it match 'Rhythm and Blues' (notice case).
it seems the elasticsearch documentation suggests using a custom analyzer of a tokenizer and lowercase filter.
here's the suggestion from elasticsearch i mentioned: (mid-page)
http://www.elasticsearch.org/blog/starts-with-phrase-matching/
I want to be able to say something like (in my POCO in pseudo code):
[ElasticProperty(Analyzer = "tokenizer, lowercase"]
public string Genre { get; set; }
Use the multi field type in your mapping. Doing so will allow you to index the Genre field in two ways- analyzed (using the standard or lowercase analyzer) for conducting searches, and not_analyzed for faceting.
For more advanced mappings like this, the attribute based mapping in NEST won't cut it. You'll have to use the fluent API, for example:
client.CreatIndex("songs", c => c
.AddMapping<Song>(m => m
.MapFromAttributes()
.Properties(props => props
.MultiField(mf => mf
.Name(s => s.Genre)
.Fields(f => f
.String(s => s.Name(o => o.Genre).Analyzer("standard"))
.String(s => s.Name(o => o.Genre.Suffix("raw")).Index(FieldIndexOption.not_analyzed)))))));
Hope this helps!

Resources