当前位置: 首页 > 面试题库 >

使用Elasticsearch C#Mpdreamz / NEST客户端在嵌套字段上进行构面

颛孙国源
2023-03-14
问题内容

如何使用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调用,则只会创建该索引。

由于您想使用嵌套类型,因此必须传递.Nested("genres")给facet调用。

您看到的数字实际上是嵌套的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));
      }

    }
  }
}


 类似资料:
  • 问题内容: 更新以显示工作示例 我正在尝试对ElasticSearch中的用户名集合进行部分搜索。 到处搜索已经为我指明了方向,但是我为正确的实施而感到困惑,但未获得任何结果。 这是我正在从事的项目中剥离的相关代码。 我尝试了不同的组合和搜索类型,但无济于事。 setup.cs Profile.cs 任何提示将不胜感激。 问题答案: 从nGram令牌过滤器上的es文档中了解一下: 注意事项 您需要

  • 问题内容: 我最近遇到了一篇博客文章,该文章描述了使用libev的TCP服务器客户端。服务器用来绑定到我熟悉的接口。但是,我也很惊讶地在客户端代码中看到。客户端代码上的相关代码如下: 具体来说,我对这一行很感兴趣: 在服务器端,我知道这会将端口绑定到所有可用接口,但是我不确定在客户端这有何意义。最后,客户端将需要在特定接口上进行连接。以前,我总是指定IP地址或使用。 Linux IP手册页没有讨论

  • 问题内容: 在尝试在Elastic Search中的文档上使用统计方面时,我遇到了一些问题。这导致在Elastic Search google组上发布了以下帖子- 请参阅https://groups.google.com/forum/#!topic/elasticsearch/wNjrnAC_KOY。我试图在有关文档中使用嵌套类型的答案中应用建议,以在collections属性上提供不同的总和(请

  • 问题内容: 我有一个客户端-服务器分层的体系结构,客户端向服务器发出类似RPC的请求。我正在使用Tomcat托管servlet,并使用Apache HttpClient对其进行请求。 我的代码是这样的: 它在负载较轻的环境中效果很好,但是当我每秒发出数百个请求时,我开始看到这种情况- 有关如何解决此问题的任何想法?我猜想这与客户端尝试重用临时客户端端口有关,但是为什么会这样/我该如何解决?谢谢!

  • 问题内容: 我开始四处寻找搜索引擎,经过一番阅读后,我决定使用ElasticSearch(这是非常了不起的:)),我的项目在C#中,所以我四处寻找客户端并开始使用NEST,一切都很简单,但是我搜索部分有些混乱。 我想搜索 特定类型的 所有字段 ,然后 输入 以下代码: 我看到许多字符串查询搜索已被弃用,并想确保上面的方法是正确的方式(上面未标记为已弃用…)对于一个简单的任务来说也有点长,所以也许有

  • 问题内容: 我正在构建一个小型聊天应用程序,其中客户端A希望通过服务器B将某些东西发送到客户端C。首先,这是解决问题的正确方法吗?我能够向服务器发送数据或从服务器接收数据,但仅限于客户端。例如,如果客户端A向服务器B发送数据而客户端C向服务器B发送数据,则我可以将数据发送回服务器A和C就像回显服务器一样。但是我想要的是将来自客户端A的数据通过服务器B转发到客户端C。 以下是服务器代码: 客户端代码