2017-06-16 39 views
1

讓我們假設我們有一個學生用(嵌套)的得分名單如下:ElasticSearch找到不同的嵌套列表元素索引對象從指定的條款

public class Student 
{ 
    public string FullName { get; set; } 
    public List<Score> Scores { get; set; } = new List<int>(); 
} 

public class Score 
{ 
    public int Value { get; set; } 
} 

我怎樣寫ElasticSearch查詢使用NEST(或簡單的查詢),以獲得至少有2個不同分數從7到10的所有學生。

因此,例如,如果學生得分{2,7,10}或{8,10},他應該在我們的結果中,而具有{10,6,5}或{8,8}或{2,7}不應該得到我們的結果。

我已經想出是:

GET /index/student/_search 
{ 
    "query": { 
    "nested": { 
     "path": "scores", 
     "query": { 
     "bool": { 
      "should": 
      [ 
      { 
       "bool": { 
       "filter": [ 
        { 
        "terms": { 
         "scores.value": [7, 10] 
        } 
        }, 
        { 
        "terms":{ 
         "scores.value": [8, 9] 
        } 
        } 
       ] 
       } 
      }, 
      { 
       "bool": { 
       "filter": [ 
        { 
        "terms": { 
         "scores.value": [7, 8] 
        } 
        }, 
        { 
        "terms":{ 
         "scores.value": [9, 10] 
        } 
        } 
       ] 
       } 
      } 
      ] 
     } 
     } 
    } 
    } 
} 

但ElasticSearch似乎並沒有允許條款連詞查詢(返回0點擊)。即使它確實有效,我仍然需要更優雅的東西,因爲如果我們有超過4個允許的值,這將是一個痛苦。

UPDATE

我嘗試了下面的腳本,但得到0的結果,以及:

GET /index/student/_search 
{ 
    "query": { 
    "nested": { 
     "path": "scores", 
     "query": { 
     "bool": { 
      "filter": [ 
      { 
       "exists": { 
       "field": "scores" 
       } 
      }, 
      { 
       "script": { 
       "script": """ 
                  boolean condition = false; 
                  def availableScores = [7, 8, 9, 10]; 
                  def scores = doc['scores.id'].values; 
                  
                  for (int i = 0; i < scores.length; i++) 
                  for(int j = 0; j < availableScores.length; j++) 
                   if (scores[i] == availableScores[j]) 
                   { 
                   if (condition == true) 
                    return (true); 
                    
                   condition = true; 
                   availableScores.remove(j); 
                   break; 
                   } 
                  return (false)""" 
       } 
      } 
      ] 
     } 
     } 
    } 
    } 
} 
+0

問題是嵌套對象,如果只是一個對象,你可以用腳本來做到這一點。我不確定你如何以數組的形式訪問值。當我測試它doc ['scores.value']。values.size()永遠是1.你有什麼額外的映射? –

+0

對不起,你實際上使用[嵌套](https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-objects.html)。由於得分沒有'[Nested]'屬性 –

+0

是的,**得分**是嵌套對象(當前示例是真正問題的模型)。我已經嘗試過使用腳本,嵌套for循環遍歷2個列表,並返回結果x) – andru6a

回答

1

很長一段時間之後,我發現一個可行的查詢:

GET /index/student/_search 
{ 
  "query": { 
    "bool": { 
      "should": [ 
        { 
          "bool": { 
            "must": [ 
              { 
                "nested": { 
                  "path": "scores", 
                  "query": { 
                    "terms": { 
                      "scores.value": [ 
                        7, 
                        10 
                      ] 
                    } 
                  } 
                } 
              }, 
              { 
                "nested": { 
                  "path": "scores", 
                  "query": { 
                    "terms": { 
                      "scores.value": [ 
                        8, 
                        9 
                      ] 
                    } 
                  } 
                } 
              } 
            ] 
          } 
        }, 
        { 
            "bool": { 
            "must": [ 
              { 
                "nested": { 
                  "path": "scores", 
                  "query": { 
                    "terms": { 
                      "scores.value": [ 
                        7, 
                        9 
                      ] 
                    } 
                  } 
                } 
              }, 
              { 
                "nested": { 
                  "path": "scores", 
                  "query": { 
                    "terms": { 
                      "scores.value": [ 
                        8, 
                        10 
                      ] 
                    } 
                  } 
                } 
              } 
            ] 
          } 
        } 
      ] 
    } 
  } 
} 

這裏的技巧是將1個嵌套查詢分隔成多個,並將他們放在should查詢。

我仍然想要一個更優雅的解決方案(通過script,我猜),但現在,我將它作爲最終答案。