2016-06-08 164 views
4

我願做一個ElasticSearch這樣的查詢:NEST條件篩選查詢

{ 
    "query" : 
    { 
     "bool" : 
     { 
      "filter" : [ 
       { 
        "terms" : 
        { 
         "name" : ["name1", "name2"] 
        } 
       }, 
       { 
        "terms" : 
        { 
         "color" : ["orange", "red"] 
        } 
       } 
      ] 
     } 
    } 
} 

我一直試圖實現它的窩是這樣的:

_elasticClient 
    .SearchAsync<MyDocument>(s => 
     s.Index("myindex") 
      .Query(q => q 
       .Bool(bq => bq 
        .Filter(fq => 
        { 
         QueryContainer query = null; 

         if (nameList.Any()) { 
          query &= fq.Terms(t => t.Field(f => f.Name).Terms(nameList)); 
         } 

         if (colorList.Any()) { 
          query &= fq.Terms(t => t.Field(f => f.Color).Terms(colorList)); 
         } 

         return query; 
        }) 
       ) 
      ) 
    ); 

但是,讓我喜歡這個地方的過濾器包裹布爾必須內查詢:

{ 
    "query" : 
    { 
     "bool" : 
     { 
      "filter" : [ 
       { 
        "bool" : 
        { 
         "must" : [ 
          { 
           "terms" : 
           { 
            "name" : ["name1", "name2"] 
           } 
          }, 
          { 
           "terms" : 
           { 
            "color" : ["orange", "red"] 
           } 
          } 
         ] 
        } 
       } 
      ] 
     } 
    } 
} 

我應該如何更改我的NEST代碼以給我正確的查詢?是否必須將我的條款添加到另一個QueryContainer

回答

7

您撥打一個查詢之前,如果你想查詢條件過濾器,如下圖所示,您可以創建一個過濾器列表:

var nameList = new[] {"a", "b"}; 
var colorList = new[] {1, 2}; 

var filters = new List<Func<QueryContainerDescriptor<MyDocument>, QueryContainer>>(); 
if (nameList.Any()) 
{ 
    filters.Add(fq=> fq.Terms(t => t.Field(f => f.Name).Terms(nameList))); 
} 

if (colorList.Any()) 
{ 
    filters.Add(fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))); 
} 

ISearchResponse<Property> searchResponse = 
    elasticClient.Search<MyDocument>(x => x.Query(q => q 
    .Bool(bq => bq.Filter(filters)))); 

如果您不需要進行篩選查詢,那麼你之前檢查任何條件能有這樣的事情:

ISearchResponse<MyDocument> searchResponse = 
elasticClient.Search<MyDocument>(x => x.Query(q => q 
.Bool(bq => bq 
.Filter(
     fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)), 
     fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)) 
     )))); 
6

一個布爾查詢的Filter方法採用params Func<QueryContainerDescriptor<T>, QueryContainer>[]這樣就可以通過它的多個表達式來表示多個過濾器

var nameList = new string[] { "name1", "name2" }; 
var colorList = new string[] { "orange", "red" }; 

client.SearchAsync<MyDocument>(s => s 
     .Index("myindex") 
     .Query(q => q 
      .Bool(bq => bq 
       .Filter(
        fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)), 
        fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)) 
       ) 
      ) 
     ) 
); 

這導致

{ 
    "query": { 
    "bool": { 
     "filter": [ 
     { 
      "terms": { 
      "name": [ 
       "name1", 
       "name2" 
      ] 
      } 
     }, 
     { 
      "terms": { 
      "color": [ 
       "orange", 
       "red" 
      ] 
      } 
     } 
     ] 
    } 
    } 
} 

NEST also has the concept of conditionless queries,即,如果查詢被確定爲conditionless,那麼它將不被序列化爲該請求的一部分。

無條件是什麼意思?那麼,這取決於查詢;例如,在terms查詢的情況下,它被認爲是conditionless如果有以下爲真

  • field不具有價值
  • 術語值列表null
  • 的項值爲空集
  • 條款值列表中有值,但它們都是null或空字符串

爲了證明

{} 

Conditionless查詢

var emptyNames = new string[] {}; 
string[] nullColors = null; 

client.SearchAsync<MyDocument>(s => 
s.Index("myindex") 
    .Query(q => q 
     .Bool(bq => bq 
      .Filter(
       fq => fq.Terms(t => t.Field(f => f.Name).Terms(emptyNames)), 
       fq => fq.Terms(t => t.Field(f => f.Color).Terms(nullColors))) 
     ) 
    ) 
); 

結果有助於使編寫NEST查詢在你越不用檢查集合具有構造查詢前值。您可以在每個查詢基礎上更改無狀態語義using .Strict() and .Verbatim()