3

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

注釈の何が問題だったのかわかりません。インデックス設定に注釈を使用するために必要な追加の構成はありますか?

4

1 に答える 1

10

こんにちはNESTの作者です。

注釈を使用する場合は、手動で呼び出す必要があります

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

インデックスへの最初の呼び出しの前。Nestオーバーヘッドが大きくなりすぎるため、各インデックス呼び出しにマッピングを適用しません。古いバージョンのelasticsearchは、インデックスが存在せず、CreateIndex呼び出しを必要としない場合にのみインデックスを作成します。

ネストされた型でファセットしたいので.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));
      }

    }
  }
}
于 2012-11-11T15:22:52.697 に答える