2017-12-15 10 views
1

私は次のようなマッピングを持つ2つのインデックス(私はそのマッピングをショートカットします)があります。Nest ElasticSearchを使用して複数のインデックスを検索する方法は?

1)AccountTypeマッピング:

elasticClient.CreateIndex("account", i => i 
       .Settings(s => s 
          .NumberOfShards(2) 
          .NumberOfReplicas(0) 
         ) 
          .Mappings(m => m 
            .Map<AccountType>(map => map 
               .AutoMap() 
               .Properties(p => p 
                .Text(c => c 
                  .Name(n => n.Name) 
                  .Analyzer("standard") 
                ) 
                .Text(c => c 
                  .Name(n => n.Description) 
                  .Analyzer("standard") 
                ) 
               ) 
            ) 
          ) 
         ); 

2)でProductTypeマッピング:

elasticClient.CreateIndex("proudct", i => i 
       .Settings(s => s 
          .NumberOfShards(2) 
          .NumberOfReplicas(0) 
         ) 
          .Mappings(m => m 
            .Map<ProductType>(map => map 
               .AutoMap() 
               .Properties(p => p 
                .Text(c => c 
                  .Name(n => n.Title) 
                  .Analyzer("standard") 
                ) 
                .Text(c => c 
                  .Name(n => n.Description) 
                  .Analyzer("standard") 
                ) 
               ) 
            ) 
          ) 
         ); 

今、私はいくつかを持っているが私がそれらをクリアする必要があるもの:

1)私の場合はアカウントであり、生産している1つのインデックスを持つことをお勧めしますtsをネストされたオブジェクトとして使用しますが、新しい製品を更新/追加するたびに、アカウント文書全体を再インデックスする必要があります。

2)私は検索機能を使用したいので、ユーザーがテキストボックスに入力して検索すると、アカウントと商品の両方に最適な一致が得られます(ここでは商品のタイトルと説明を検索しますプラスアカウントの当時の名前と説明ベストマッチを得る):

だからここネストElasticSeachを使用して複数のインデックスに対して検索する方法、あるいはそれが不可能な場合は、最良の取得、すべてのインデックスからベストマッチを得るための良いアイデアですスコアに応じて両方の結果から一致しますか?

PS:ここ は、商品インデックス内で検索するための例です:

 var result = elasticClient.Search<ProductType>(s => s 
              .Size(10) 
              .Query(q => q 
               .MultiMatch(m => m 
               .Fields(f => f.Field(p => p.Title, 1.5).Field(p => p.Description, 0.8)) 
               .Operator(Operator.Or) 
               .Query(query) 
              ) 
              ) 
             ); 

答えて

1

1)まず、私の場合にはアカウントで、ネストされたオブジェクトなどの製品を持っている一つのインデックスを持つことは良いアイデアですしかし、ここで私は毎回新しい製品を更新/追加したいのですが、私はアカウント文書全体を再索引付け(更新)する必要がありますか?

インデックスごとに1つのタイプと、in Elasticsearch 6.0+, you can only have one type per indexを持つことをお勧めします。製品がアカウントのネストされたオブジェクトとして表される場合、アカウントに新しい製品を追加するには、アプリケーションコード内の、またはElasticsearch内のいずれかのドキュメントを更新する必要があります。

2)私は検索機能を使用したいので、ユーザーがテキストボックスに入力して検索すると、アカウントと商品の両方でベストマッチを得たいと考えています(ここでは商品のタイトルその後、説明を加えたアカウントの名前と説明ベストマッチを得る):

あなたはthe documentation of covariant search resultsをチェックアウトし、複数のインデックス間で検索することができます。 1つのインデックスから複数の異なる型を返す例を示します(この例では6.0が更新されます)。これは複数のインデックスにわたって実行できます。ここでは例です:

private static void Main() 
{ 
    var settings = new ConnectionSettings(new Uri("http://localhost:9200")) 
     .InferMappingFor<AccountType>(i => i 
      .IndexName("account") 
     ) 
     .InferMappingFor<ProductType>(i => i 
      .IndexName("product") 
     ) 
     // useful for development, to make the request/response bytes 
     // available on the response 
     .DisableDirectStreaming() 
     // indented JSON in requests/responses 
     .PrettyJson() 
     // log out all requests/responses 
     .OnRequestCompleted(callDetails => 
     { 
      if (callDetails.RequestBodyInBytes != null) 
      { 
       Console.WriteLine(
        $"{callDetails.HttpMethod} {callDetails.Uri} \n" + 
        $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}"); 
      } 
      else 
      { 
       Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}"); 
      } 

      Console.WriteLine(); 

      if (callDetails.ResponseBodyInBytes != null) 
      { 
       Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" + 
         $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" + 
         $"{new string('-', 30)}\n"); 
      } 
      else 
      { 
       Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" + 
         $"{new string('-', 30)}\n"); 
      } 
     }); 

    var client = new ElasticClient(settings); 

    if (client.IndexExists("account").Exists) 
     client.DeleteIndex("account"); 

    client.CreateIndex("account", i => i 
     .Settings(s => s 
      .NumberOfShards(2) 
      .NumberOfReplicas(0) 
     ) 
     .Mappings(m => m 
      .Map<AccountType>(map => map 
       .AutoMap() 
       .Properties(p => p 
        .Text(c => c 
         .Name(n => n.Name) 
         .Analyzer("standard") 
        ) 
        .Text(c => c 
         .Name(n => n.Description) 
         .Analyzer("standard") 
        ) 
       ) 
      ) 
     ) 
    ); 

    if (client.IndexExists("product").Exists) 
     client.DeleteIndex("product"); 

    client.CreateIndex("product", i => i 
     .Settings(s => s 
      .NumberOfShards(2) 
      .NumberOfReplicas(0) 
     ) 
     .Mappings(m => m 
      .Map<ProductType>(map => map 
       .AutoMap() 
       .Properties(p => p 
        .Text(c => c 
         .Name(n => n.Title) 
         .Analyzer("standard") 
        ) 
        .Text(c => c 
         .Name(n => n.Description) 
         .Analyzer("standard") 
        ) 
       ) 
      ) 
     ) 
    ); 

    client.IndexMany(new[] { 
     new AccountType { Name = "Name 1", Description = "Description 1" }, 
     new AccountType { Name = "Name 2", Description = "Description 2" }, 
     new AccountType { Name = "Name 3", Description = "Description 3" }, 
     new AccountType { Name = "Name 4", Description = "Description 4" }, 
    }); 

    client.IndexMany(new[] { 
     new ProductType { Title = "Title 1", Description = "Description 1" }, 
     new ProductType { Title = "Title 2", Description = "Description 2" }, 
     new ProductType { Title = "Title 3", Description = "Description 3" }, 
     new ProductType { Title = "Title 4", Description = "Description 4" }, 
    }); 

    var indices = Indices.Index(typeof(ProductType)).And(typeof(AccountType)); 

    client.Refresh(indices); 

    var searchResponse = client.Search<object>(s => s 
     .Index(indices) 
     .Type(Types.Type(typeof(ProductType), typeof(AccountType))) 
     .Query(q => (q 
      .MultiMatch(m => m 
       .Fields(f => f 
        .Field(Infer.Field<ProductType>(ff => ff.Title, 1.5)) 
        .Field(Infer.Field<ProductType>(ff => ff.Description, 0.8)) 
       ) 
       .Operator(Operator.Or) 
       .Query("Title 1") 
      ) && +q 
      .Term("_index", "product")) || (q 
      .MultiMatch(m => m 
       .Fields(f => f 
        .Field(Infer.Field<AccountType>(ff => ff.Name, 3)) 
        .Field(Infer.Field<AccountType>(ff => ff.Description, 0.3)) 
       ) 
       .Operator(Operator.Or) 
       .Query("Name 4") 
      ) && +q 
      .Term("_index", "account")) 
     ) 
    ); 

    foreach (var document in searchResponse.Documents) 
     Console.WriteLine($"document is a {document.GetType().Name}"); 
} 

public class ProductType 
{ 
    public string Title { get; set; } 
    public string Description { get; set; } 
} 

public class AccountType 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

結果が

document is a AccountType 
document is a ProductType 
document is a AccountType 
document is a ProductType 
document is a AccountType 
document is a AccountType 
document is a ProductType 
document is a ProductType 

で起こって多くはので、私が説明させてここにあります。

POST http://localhost:9200/product%2Caccount/producttype%2Caccounttype/_search?pretty=true 
{ 
    "query": { 
    "bool": { 
     "should": [ 
     { 
      "bool": { 
      "must": [ 
       { 
       "multi_match": { 
        "query": "Title 1", 
        "operator": "or", 
        "fields": [ 
        "title^1.5", 
        "description^0.8" 
        ] 
       } 
       } 
      ], 
      "filter": [ 
       { 
       "term": { 
        "_index": { 
        "value": "product" 
        } 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "bool": { 
      "must": [ 
       { 
       "multi_match": { 
        "query": "Name 4", 
        "operator": "or", 
        "fields": [ 
        "name^3", 
        "description^0.3" 
        ] 
       } 
       } 
      ], 
      "filter": [ 
       { 
       "term": { 
        "_index": { 
        "value": "account" 
        } 
       } 
       } 
      ] 
      } 
     } 
     ] 
    } 
    } 
} 

検索はproducttypeaccounttypeタイプで、両方productaccount指数全体で実行されます。検索要求JSONは次のようになります。 titleフィールドとdescriptionフィールドでmulti_matchクエリが実行され、boolクエリを使用する用語クエリと組み合わせて、クエリをproductインデックスに制約します。用語クエリに対して関連性スコアを計算しないため、クエリという用語はフィルタ句に含まれています。このbool照会は、nameおよびdescriptionフィールドでmult_match照会を実行する別のbool照会と組み合わされ、照会をaccount索引に制約する用語照会でcmbinedされます。 2つのbool照会は、いずれかのbool照会または他の照会のいずれかが一致する必要があるため、句を使用して結合されます。

object

ProductTypeAccountTypeは、共通の基本クラスを共有していないので(! object以外) Search<T>()メソッド呼び出しのための一般的なパラメータの型として使用された文書コレクションを入力することができます。しかし、この結果から、NESTは producttypeのインスタンスを ProductTypeのインスタンスに、 accounttypeのインスタンスを AccountTypeのドキュメントに実際に非直列化したことがわかります。

クエリでは、クエリをより簡潔に組み合わせるためにoperator overloadingが使用されます。

+0

あなたは巣弾性検索のマスターです。私が質問をするたびに、私はあなたからの正確な答えを得ます。あなたのあまりにも詳細な答えにはとても感謝しています。 –

+1

「地獄のような」願望はいいです:)助けて嬉しいです –

+0

私の悪い英語のために申し訳ありません。それは "地獄のように"悪い意味を持っていると思われる –

関連する問題