2012-11-17 42 views
5

Tôi có một thử thách thú vị, mà tôi nghĩ có một câu trả lời dễ dàng."Tự động" tạo bộ lọc trong NEST

Tôi biết rằng bộ lọc NEST hoạt động chính xác khi cú pháp bạn làm điều gì đó như thế này:

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

dịch vụ cơ sở của tôi nên cho phép một người gọi để vượt qua trong một số loại danh sách đếm được của các mục để lọc.

tôi về cơ bản muốn để có thể lập trình đạt được một cái gì đó như thế này (bộ lọc được truyền vào phương pháp):

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

Nói cách khác nếu tôi trôi qua trong một mảng của {{ "first.name" "joe"}, { "first.name", "jim"}, { "first.name", "thẳng thắn"}} tôi muốn để sản xuất tương đương với

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

Trả lời

8

Sử dụng lambda dựa DSL bạn có thể làm như sau:

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

Mà tôi nghĩ đọc tốt hơn một chút :)

Nest bây giờ cũng hỗ trợ conditionless truy vấn vì vậy nếu bất kỳ tp.SearchValuesnull, empty hoặc all empty strings hoặc tp.SearchFieldnull or empty nó sẽ bỏ qua mà truy vấn về/tiền tố.

Bạn có thể trở lại hành vi này một cách dễ dàng mặc dù:

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

mà sẽ ném một DslException nếu một truy vấn có sản phẩm nào được tạo ra.

Lưu ý cuối cùng client.Search() sẽ trả lại QueryResult<dynamic> nếu bạn có thể nhập mạnh tài liệu của mình để có thể thực hiện client.Search<MyDocument>().

-1

tôi đã có thể giải quyết điều này sau khi một số R & D về chủ đề với một cái gì đó giống như sau. Tôi sẽ cần phải làm một số công việc bổ sung đối với AND và OR hỗ trợ:

 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

Câu trả lời của Martijn là tốt nhất nhưng tôi nghĩ tôi sẽ thêm một ví dụ mà tôi đã tạo đang làm việc cho tôi, hy vọng nó sẽ hữu ích cho người khác. Tôi đã xây dựng một danh sách các đối tượng BaseQuery và sau đó đặt nó trong truy vấn của tôi bằng cách sử dụng phương thức .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)) 
       ); 
Các vấn đề liên quan