Say I got an ElasticSearch up and running with and Blog object.
public class Blog
{
[ElasticProperty(Name = "guid", Index = FieldIndexOption.NotAnalyzed, Type = FieldType.String)]
public Guid? Guid { get; set; }
[ElasticProperty(Name = "title", Index = FieldIndexOption.Analyzed, Type = FieldType.String)]
public string Title { get; set; } = "";
[ElasticProperty(Name = "body", Index = FieldIndexOption.Analyzed, Type = FieldType.String)]
public string Body { get; set; } = "";
[ElasticProperty(Name = "publishedDate", Index = FieldIndexOption.Analyzed, Type = FieldType.Date)]
public DateTime PublishedDate { get; set; }
}
Now I would only like to return a subset of the properties into a new class
public class BlogListItem
{
public static Expression<Func<Blog, object>> Selector = e => new BlogListItem
{
Title = e.Title,
PublishedDate = e.PublishedDate,
};
public string Title { get; set; }
public DateTime PublishedDate { get; set; }
}
Normally I work with Entity Framework where I would write an Selector like in the BlogListItem class, but I'm finding it hard to find any information about doing this in ElasticSearch with NEST
var res = elastic.Search<Blog>(s => s
.From(0)
.Size(3)
.Index(blogIndex)
.Query(q => q.MatchAll())
.Sort(o => o.OnField(p => p.PublishedDate))
.Fields(BlogListItem.Selector)
);
var result = res.Hits.Select(e => e.Source).ToList();
This returns the correct number of Hits, but with an null source and I can't figure out where to find the returned properties.
Solution 1 I found an alternative solution, but would like input if this is a good solution.
var res2 = elastic.Search<Blog, BlogListItem>(s => s
.From(0)
.Size(3)
.Index(blogIndex)
.Query(q => q.MatchAll())
.Sort(o => o.OnField(p => p.PublishedDate))
);
List<BlogListItem> resultList = res2.Hits.Select(hit => hit.Source).ToList();
This gives me the correct object returned, but I don't have any control about mapping, and I'm not sure if it returns all properties and then do the mapping.
Solution 2.5 In this solution i have updated my BlogListItem with a new Selector.
public class BlogListItem
{
public static SearchSourceDescriptor<Blog> Selector(SearchSourceDescriptor<Blog> sr)
{
return sr.Include(fi => fi.Add(f => f.Title));
}
[ElasticProperty(Name = "title")]
public string TitleNewName { get; set; }
public DateTime PublishedDate { get; set; }
}
And then my elasticSearch code
var res3 = elastic.Search<Blog, BlogListItem>(s => s
.From(0)
.Size(3)
.Index(blogIndex)
.Query(q => q.MatchAll())
.Sort(o => o.OnField(p => p.PublishedDate))
.Source(BlogListItem.Selector)
);
List<BlogListItem> resultList = res3.Hits.Select(hit => hit.Source).ToList();
Now this limits the properties returned so I only get Title and the PublishedDate is null and I know have control on the mapping thanks to
[ElasticProperty(Name = "title")]
Still needs to verify if this is the correct way of working with ElasticSearch.
This produces the following Json
{
"from": 0,
"size": 3,
"sort": [
{
"publishedDate": {}
}
],
"_source": {
"include": [
"title"
]
},
"query": {
"match_all": {}
}
}