2012-11-17 5 views
5

興味深い課題があります。簡単な答えがあると思います。NESTで「動的に」フィルタを作成する

var andFilter = FilterFactory.AndFilter(
        FilterFactory.TermFilter("name.first", "shay1"), 
        FilterFactory.TermFilter("name.first", "shay4") 
       ); 

私の基本サービスは、発信者がフィルタリングする項目の列挙リストのいくつかの並べ替えに渡すことができるようにする必要があります

は、私はあなたがこのような何かを行うときに構文的NESTフィルタが正常に動作していることを知っています。私は{{「first.name」の配列に渡された場合は、他の言葉で

var andFilter = new FilterDescriptor(); 
foreach (var filter in filters) 
{ 
    andFilter = filter concatenated to andFilter 
} 

私は基本的に、プログラムできるように、このような何かを(フィルタがメソッドに渡される)を達成したいのですが、 "ジョー"}、{ "first.name"、 "ジム"}、{ "first.name"、 "フランク"}}私は

var andFilter = FilterFactory.AndFilter(
        FilterFactory.TermFilter("name.first", "joe"), 
        FilterFactory.TermFilter("name.first", "joe"), 
        FilterFactory.TermFilter("name.first", "frank") 
       ); 

答えて

8

:私は、ANDとORの支持体上にいくつかの追加の作業を行う必要があります私が思う

var termsFilters = from tp in termParameters 
        let field = ToCamelCaseNestedNames(tp.SearchField) 
        let terms = tp.SearchValues 
        select Filter.Terms(field, terms); 

var prefixFilters = from tp in prefixParameters 
        let field = ToCamelCaseNestedNames(tp.SearchField) 
        let prefix = tp.SearchValues.FirstOrDefault().ToLowerInvariant() 
        select Filter.Prefix(field, prefix); 

var search = client.Search(s => s 
    .From(0) 
    .Size(20) 
    .Filter(f => f.And(termsFilters.Concat(prefixFilters).ToArray())) 
); 

読み取り少し良くを:)

巣は今もあらゆるtp.SearchValuesは、emptyまたはall empty stringstp.SearchFieldnullあるので、もしconditionlessクエリをサポートしています、それは用語/プレフィックスクエリというスキップしますnull or emptyです。

あなたはかかわらず、簡単にこの動作を元に戻すことができます。

空のクエリが発生した場合 DslExceptionをスローします
var search = client.Search(s => s 
    .Strict() 
    .From(0) 
    .Size(20) 
    .Filter(f => f.And(termsFilters.Concat(prefixFilters).ToArray())) 
); 

最後に、client.Search()は文書を強く入力できる場合はQueryResult<dynamic>を返しますので、client.Search<MyDocument>()とすることができます。

-1

と同等のものを生成したい私は解決することができましたこれは、被験者のR & Dの後に、以下のようなものがあります。あなたは次の操作を行うことができますラムダベースのDSLを使用して

 IList<IFilterBuilder> conditions = new List<IFilterBuilder>(); 
     if (termParameters != null) 
      foreach (var termParameter in termParameters) 
       conditions.Add(FilterFactory.TermsFilter(ToCamelCaseNestedNames(termParameter.SearchField), termParameter.SearchValues)); 

     if (prefixParameters != null) 
      foreach (var prefixParameter in prefixParameters) 
       conditions.Add(FilterFactory.PrefixFilter(ToCamelCaseNestedNames(prefixParameter.SearchField), prefixParameter.SearchValues.First().ToLowerInvariant())); 

     var filters = FilterFactory.AndFilter(); 
     filters.Add(FilterFactory.AndFilter(conditions.ToArray())); 

     MatchAllQueryBuilder matchAllQueryBuilder = new MatchAllQueryBuilder(); 
     FilteredQueryBuilder filteredQueryBuilder = new FilteredQueryBuilder(matchAllQueryBuilder, filters); 
     SearchBuilder searchBuilder = new SearchBuilder(); 
     searchBuilder.Query(filteredQueryBuilder); 
     searchBuilder.Size(maxResults); 
1

Martijnの答えは最高ですが、私が作成した例を追加して、私のために働いていれば、うまくいけば他の人に役立つでしょう。私はBaseQueryオブジェクトのリストを作成し、それを.ToArray()メソッドを使ってクエリに配置しました。

#region build query 

    var query = new List<BaseQuery> 
       { 
        Query<IAuthForReporting>.Range(r => r.OnField(f => f.AuthResult.AuthEventDate) 
                .From(authsByDateInput.StartDate.ToEPCISFormat()) 
                .To(authsByDateInput.EndDate.ToEPCISFormat())) 
       }; 
    if (authsByDateInput.AuthResult != AuthResultEnum.SuccessOrFailure) 
    { 
     var success = authsByDateInput.AuthResult == AuthResultEnum.Success; 
     query.Add(Query<IAuthForReporting>.Term(t => t.AuthResult.AuthenticationSuccessful, success)); 
    } 
    if (authsByDateInput.ProductID != null) 
    { 
     query.Add(Query<IAuthForReporting>.Term(t => t.AuthResult.ProductID, authsByDateInput.ProductID.Value)); 
    } 

    if (!authsByDateInput.CountryIDs.IsNullOrEmpty()) 
    { 
     query.Add(Query<IAuthForReporting>.Terms(t => t.AuthResult.Address.CountryID, authsByDateInput.CountryIDs.Select(x=> x.Value.ToString()).ToArray())); 
    } 
    #endregion 

     var result = 
      ElasticClient.Search<IAuthForReporting>(s => 
                s.Index(IndexName) 
                .Type(TypeName) 
                .Size(0) 
                .Query(q => 
                  q.Bool(b => 
                    b.Must(query.ToArray()) 
                   ) 
                 ) 
                .FacetDateHistogram(t => t.OnField(f => f.AuthResult.AuthEventDate).Interval(DateInterval.Day)) 
       ); 
関連する問題