如何使用 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 */
        }
    }
}

作为方面的结果,我得到:
  • 流派 (842)
  • 98 (47)
  • 51 (30)
  • 24 (29)
  • 46 (28)

  • 虽然我希望得到类似的东西:
  • 类型 1 (842)
  • 类型 2 (47)
  • 类型 3 (30)
  • 类型 4 (29)
  • 流派 5 (28)

  • 我做错了什么?在哪里检查在 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 调用,则旧版本的 elasticsearch 只会创建索引。

    由于您想对嵌套类型进行分面,因此必须将 .Nested("genres") 传递给分面调用。

    你看到的数字实际上是嵌套的 docids :)

    这是我修改后的 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));
          }
    
        }
      }
    }
    

    关于elasticsearch - 带有 Elasticsearch C# Mpdreamz/NEST 客户端的嵌套字段的 Facet,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13218346/

    10-11 08:52
    查看更多