c# - ElasticSearch从指定术语中查找具有不同嵌套列表元素的索引对象

标签 c# elasticsearch nest elasticsearch-painless

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

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 查询,以获取所有分数在7到10之间至少2的所有学生。

因此,例如,如果某个学生的得分为{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命中)的连接。即使它确实起作用,我仍然需要一些更优雅的东西,因为如果我们有四个以上的允许值,这将很痛苦。

更新

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

最佳答案

一段时间后,我发现了一个有效的查询:

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,我想),但是现在,我将其保留为最终答案。

关于c# - ElasticSearch从指定术语中查找具有不同嵌套列表元素的索引对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44594825/

相关文章:

c# - Microsoft.Xrm.Sdk.EntityReference.Equals(obj) 行为

search - 我是否需要在Elasticsearch过滤器中优化 bool 表达式?

elasticsearch - 如何从ElasticSearch获取详细的结果输出

elasticsearch - 通过 kibana 进行 Elasticsearch 累积和聚合

c# - 从爱尔兰的服务器获取丹麦的本地日期时间

c# - 使用代码契约使泛型成为枚举类型

c# - 使用 Microsoft Fakes 进行模拟

elasticsearch - 如何使用elasticsearch nest API创建自定义分析器以忽略重音和pt-br停用词?

c# - 如何将一个not_analyzed字段添加到Elasticsearch中

elasticsearch - Elasticsearch:创建索引时设置的总字段数限制