'ElasticSearch NEST, map the search response directly to a ViewModel class that is different from the ElasticSeach Index class

I am using NEST 7.17.0 and Elasticsearch 7.16.2

I'd like to know how I can map my search response directly to my ViewModel class without any transforming in C#.

I have an ElasticIndex called "PublicLegislationResult", and a ViewModel called "ViewEntities.PublicLegislationDetail" with a subset of the properties that exist in the ElasticSearch index.

The properties in the ViewModel class are not necessarily the same as the ones in the main index. Ex: "ItemSubCategory"(index) => "SubCategory" (ViewModel)

This search query works:

ISearchResponse<PublicLegislationResult> searchResults;

searchResults = await this.Client
                     .SearchAsync<PublicLegislationResult>(s =>
                         this.GetPublicSearchDescriptor(s)
                         .Query(q => q
                            .Bool(b => b
                                .Must(m => m.Match(mt => mt.Field(f => f.CalendarYear).Query(searchCriteria))))));

return searchResults;

But I have to additionally transform the results to my ViewModel as such

List<PublicLegislationResult> publiclegislationHitList = publicLegislationResult.Hits?.Select(t => t.Source).ToList();
fileDetailList = publiclegislationHitList?.Select(t => new ViewEntities.PublicLegislationDetail(){
   ...
}.ToList();

I have tried this:


ISearchResponse<ViewEntities.PublicLegislationDetail> searchResults;

searchResults = await this.Client
                     .SearchAsync<ViewEntities.PublicLegislationDetail>(s =>
                         this.GetPublicSearchDescriptor(s)
                         .Query(q => q
                            .Bool(b => b
                                .Must(m => m.Match(mt => mt.Field(f => f.CalendarYear).Query(searchCriteria))))));
return searchResults;

This partially works (surprisingly) because the ViewModel object closely matches the index and NEST is able to map the properties with exact matching names, the rest are returned as NULL

Hence my question: If NEST is able to do this much out-of-the-box, is there a way to explicitly map the properties of the index to my view model so that I can skip the transformation step completely?

Any help figuring this out would be greatly appreciated, thanks!



Solution 1:[1]

You can deserialize _source JSON documents in Elasticsearch to any POCO type to which the JSON property names and types map to POCO properties.

NEST serializes POCO property names to camel case JSON properties by default, and attempts to match JSON properties to POCO properties by camel casing the POCO property names; if there's a match on name, it will attempt to assign the JSON value to the POCO property by using a registered JsonFormatter to deserialize the JSON type to a CLR type.

If a property name will not match by convention, you can use attributes such as PropertyNameAttribute on the POCO property to indicate the name in JSON, or use fluent mapping to indicate the names.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Russ Cam