如何使用Mpdreamz / NEST Elasticsearch客户端基于嵌套字段的属性列出构面?
我检查了Nest文档,但不清楚如何执行。
这是我尝试的代码:
using System; using System.Collections.Generic; using System.Linq; using Nest; namespace Demo { class Program { public class Movie { public int Id { get; set; } public string Title { get; set; } public string Description { get; set; } [ElasticProperty(Index = FieldIndexOption.analyzed, Type = FieldType.nested)] public List<Genre> Genres { get; set; } public int Year { get; set; } } public class Genre { // public int Id { get; set; } [ElasticProperty(Index = FieldIndexOption.analyzed)] public string GenreTitle { get; set; } } static void Main(string[] args) { var setting = new ConnectionSettings("localhost", 9200); setting.SetDefaultIndex("default_index"); var client = new ElasticClient(setting); // delete previous index with documents client.DeleteIndex<Movie>(); // put documents to the index var genres = new List<Genre>(); for (var i = 0; i < 100; i++) genres.Add(new Genre { GenreTitle = string.Format("Genre {0}", i) }); for (var i = 0; i < 1000; i++) { client.Index(new Movie { Id = i, Description = string.Format("Some movie description {0}", i), Title = string.Format("Movie Title {0}", i), Year = 1980 + (i % 10), Genres = genres.OrderBy(x => Guid.NewGuid()).Take(10).ToList() }); } // query with facet on nested field property genres.genreTitle var queryResults = client.Search<Movie>(x => x .From(0) .Size(10) .MatchAll() .FacetTerm(t => t .OnField(f => f.Year) .Size(30)) .FacetTerm(t => t .Size(5) .OnField(f => f.Genres.Select(f1 => f1.GenreTitle) ) ) ); var yearFacetItems = queryResults.FacetItems<FacetItem>(p => p.Year); foreach (var item in yearFacetItems) { var termItem = item as TermItem; Console.WriteLine(string.Format("{0} ({1})", termItem.Term, termItem.Count)); } /* Returns: 1989 (90) 1988 (90) 1986 (90) 1984 (90) 1983 (90) 1981 (90) 1980 (90) 1987 (89) 1982 (89) 1985 (88) and it's fine! */ var genresFacetItems = queryResults.FacetItems<FacetItem>(p => p.Genres.Select(f => f.GenreTitle)); foreach (var item in genresFacetItems) { var termItem = item as TermItem; Console.WriteLine(string.Format("{0} ({1})", termItem.Term, termItem.Count)); } /* Return soemthing: genre (842) 98 (47) 51 (30) 24 (29) 46 (28) and it's BAD! I expect the Genre Title to be listed as string, not as some strange integer */ } } }
由于构面,我得到:
虽然我希望得到类似的东西:
我做错了什么?在哪里检查在Nest和嵌套面上使用嵌套字段的正确方法?
谢谢。
更新1:
我发现它与令牌生成器/分析器有关。如果流派名称没有空格或破折号-一切正常。我也尝试了未分析的索引属性
[ElasticProperty(Index = FieldIndexOption.not_analyzed)] public string GenreTitle { get; set; }
但这没有帮助
更新2: 我在之前的索引删除之后添加了流利的索引映射,而不是注释,例如:
var settings = new IndexSettings(); var typeMapping = new TypeMapping("movies"); var type = new TypeMappingProperty { Type = "string", Index = "not_analyzed", Boost = 2.0 // Many more options available }; typeMapping.Properties = new Dictionary<string, TypeMappingProperty>(); typeMapping.Properties.Add("genres.genreTitle", type); settings.Mappings.Add(typeMapping); client.CreateIndex("default_index", settings);
现在不确定注解出了什么问题。使用注释进行索引设置是否需要其他配置?
嗨,NEST的作者在这里,
如果您使用注释,则需要手动调用
var createIndex = client.CreateIndex("default_index", new IndexSettings { }); client.Map<Movie>();
在第一次调用索引之前。Nest不会将映射应用于每个索引调用,因为这会产生过多的开销。如果弹性索引的旧版本不存在并且不需要CreateIndex调用,则只会创建该索引。
Nest
CreateIndex
由于您想使用嵌套类型,因此必须传递.Nested("genres")给facet调用。
.Nested("genres")
您看到的数字实际上是嵌套的docid :)
这是我修改后的program.cs,可以正常工作:
using System; using System.Collections.Generic; using System.Linq; using Nest; namespace Demo { class Program { public class Movie { public int Id { get; set; } public string Title { get; set; } public string Description { get; set; } [ElasticProperty(Type=FieldType.nested)] public List<Genre> Genres { get; set; } public int Year { get; set; } } public class Genre { // public int Id { get; set; } [ElasticProperty(Index = FieldIndexOption.not_analyzed)] public string GenreTitle { get; set; } } static void Main(string[] args) { var setting = new ConnectionSettings("localhost", 9200); setting.SetDefaultIndex("default_index"); var client = new ElasticClient(setting); // delete previous index with documents client.DeleteIndex<Movie>(); var createIndexResult = client.CreateIndex("default_index", new IndexSettings { }); var mapResult = client.Map<Movie>(); // put documents to the index var genres = new List<Genre>(); for (var i = 0; i < 100; i++) genres.Add(new Genre { GenreTitle = string.Format("Genre {0}", i) }); for (var i = 0; i < 1000; i++) { client.Index(new Movie { Id = i, Description = string.Format("Some movie description {0}", i), Title = string.Format("Movie Title {0}", i), Year = 1980 + (i % 10), Genres = genres.OrderBy(x => Guid.NewGuid()).Take(10).ToList() }); } // query with facet on nested field property genres.genreTitle var queryResults = client.Search<Movie>(x => x .From(0) .Size(10) .MatchAll() .FacetTerm(t => t .OnField(f => f.Year) .Size(30)) .FacetTerm(t => t .Size(5) .OnField(f => f.Genres.Select(f1 => f1.GenreTitle)) .Nested("genres") ) ); var yearFacetItems = queryResults.FacetItems<FacetItem>(p => p.Year); foreach (var item in yearFacetItems) { var termItem = item as TermItem; Console.WriteLine(string.Format("{0} ({1})", termItem.Term, termItem.Count)); } var genresFacetItems = queryResults.FacetItems<FacetItem>(p => p.Genres.Select(f => f.GenreTitle)); foreach (var item in genresFacetItems) { var termItem = item as TermItem; Console.WriteLine(string.Format("{0} ({1})", termItem.Term, termItem.Count)); } } } }