与Elasticsearch C#Mpdreamz / NEST客户端嵌套字段的方面 [英] Facet on nested field with Elasticsearch C# Mpdreamz/NEST client

查看:542
本文介绍了与Elasticsearch C#Mpdreamz / NEST客户端嵌套字段的方面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用Mpdreamz / NEST Elasticsearch客户端基于嵌套字段的属性列出方面?

How to list a facet based on a property of a nested field using Mpdreamz/NEST Elasticsearch client?

我检查了Nest文档,但是还不清楚如何

I checked the Nest documentation, but it's not clear how to do it.

这是我尝试的代码:

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)

  • genre (842)
  • 98 (47)
  • 51 (30)
  • 24 (29)
  • 46 (28)

虽然我希望得到以下内容:

While I expect to get something like:


  • 流派1(842)

  • 流派2(47)

  • 流派3 (30)

  • 流派4(29)

  • 流派5(28)

  • Genre 1 (842)
  • Genre 2 (47)
  • Genre 3 (30)
  • Genre 4 (29)
  • Genre 5 (28)

我做错了什么?在哪里检查巢穴和面上使用嵌套字段的正确方法?

What do I do wrong? Where to check the right way of using nested fields in Nest and facets on them?

谢谢。

更新1:

我发现它与tokenizer / analyzer有关。如果流派名称没有空格或破折号 - 一切正常。
我也尝试未分析的索引属性

I found it has something to do with tokenizer/analyzer. If genre name is without spaces or dashes - everything works fine. I also tried not-analyzed index attribute

[ElasticProperty(Index = FieldIndexOption.not_analyzed)]
public string GenreTitle { get; set; }

但没有帮助

更新2:
我以前的索引删除之前添加了流畅的索引映射,而不是注释:

Update 2: I added fluent index mapping instead of annotations right after previous index delete like:

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);

现在不知道注释有什么问题。是否有任何额外的配置需要使用注解索引设置?

Now not sure what was wrong with annotations. Is there any additional config needed to use annotations for index settings?

推荐答案

Hi NEST的作者在这里,

Hi Author of NEST here,

如果您使用注释,您需要手动调用

If you use the annotations you need to manually call

var createIndex = client.CreateIndex("default_index", new IndexSettings { });
client.Map<Movie>();

在首次调用索引之前。 Nest 不会在每个索引调用上应用映射,因为这将导致太多的开销。如果弹性搜索的较旧版本不存在,则只需创建索引,并且不需要 CreateIndex 调用。

Before the first call to index. Nest wont apply the mapping on each index call since that would incur too much of overhead. Older versions of elasticsearch would just create the index if it doesn't exist and would not need the CreateIndex call.

因为你想要嵌套类型,你必须通过 .Nested(genres)到facet调用。

Since you want to facet on a nested type you have to pass .Nested("genres") to the facet call.

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

The numbers you saw were actually the nested docids :)

这是我修改过的program.cs,它有效:

Here's my modified program.cs that works:

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 C#Mpdreamz / NEST客户端嵌套字段的方面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆