2012-11-17 20 views
5

में एक फ़िल्टर बनाना मेरे पास एक दिलचस्प चुनौती है, जो मुझे लगता है कि इसका एक आसान जवाब है।"गतिशील रूप से" नेस्ट

मुझे पता है कि घोंसला फिल्टर सही ढंग से काम जब वाक्य रचना आप कुछ इस तरह करते हैं:

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

मेरे आधार सेवाओं एक फोन करने वाले फिल्टर करने के लिए मदों की गणनीय सूची में किसी प्रकार का में पारित करने के लिए अनुमति चाहिए।

मैं मूल रूप से (फिल्टर विधि में पारित हो जाता) कुछ इस तरह प्राप्त प्रोग्राम के रूप में सक्षम होने के लिए करना चाहते हैं:

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

दूसरे शब्दों में अगर मैं {{ "first.name" की एक सरणी में पारित , "जो"}, { "first.name", "जिम"}, { "first.name", "खुलकर"}} मैं

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

उत्तर

8

लैम्ब्डा आधारित डीएसएल का उपयोग करके आप निम्न कर सकते हैं: मैं और और या समर्थन पर कुछ अतिरिक्त काम करने की आवश्यकता होगी

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.SearchValuesnull, empty या all empty strings या tp.SearchField है null or empty है यह है कि नियम/उपसर्ग क्वेरी को छोड़ देगा

नेस्ट अब भी conditionless प्रश्नों का समर्थन करता है।

आप इस व्यवहार को वापस कर सकते हैं आसानी से हालांकि:

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

जो एक DslException फेंक देते हैं, तो एक खाली क्वेरी उत्पन्न होता है।

अंतिम नोट client.Search() एक QueryResult<dynamic> वापस कर देगा यदि आप दृढ़ता से अपने दस्तावेज़ टाइप कर सकते हैं तो client.Search<MyDocument>() कर सकते हैं।

-1

मैं हल करने में सक्षम था के बराबर का उत्पादन करना चाहते हैं इस विषय पर कुछ आर & डी के बाद कुछ ऐसा है।

 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

मार्टिजन का जवाब सबसे अच्छा है, लेकिन मैंने सोचा कि मैं एक उदाहरण जोड़ूंगा जो मैंने बनाया है जो मेरे लिए काम कर रहा है, उम्मीद है कि यह दूसरों के लिए सहायक होगा। मैंने बेसक्वायर ऑब्जेक्ट्स की एक सूची बनाई और फिर .oArray() विधि का उपयोग करके मेरी क्वेरी में डाल दिया।

#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)) 
       ); 
संबंधित मुद्दे