1

假设我们有一个(嵌套)分数列表的学生,如下所示:

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; }
}

如何使用NEST (或简单查询)编写ElasticSearch查询以获取至少有 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 似乎不允许TERMS查询的结合(返回 0 个命中)。即使它确实有效,我仍然需要更优雅的东西,因为如果我们有超过 4 个允许的值,这将变得很痛苦。

更新

我尝试了以下脚本,但也得到了 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)"""
              }
            }
          ]
        }
      }
    }
  }
}
4

1 回答 1

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我猜是通过 a ),但现在,我将把它作为最终答案。

于 2017-06-22T10:28:05.353 回答