如何在ElasticSearch中从数组中获取不同范围的值计数,每个文档都是独立的?

q1qsirdb  于 2022-12-29  发布在  ElasticSearch
关注(0)|答案(1)|浏览(99)

我想从每个文档的数组中获取不同范围的值的计数。例如,学生的文档包含数组“grades”,该数组的每个科目都有不同的分数,如数学-分数71,科学-分数91等。因此,我想获取每个学生的范围,如A - 2级科目,B - 1级科目。
所以,Map是这样的:

{
  "student-grades": {
    "mappings": {
      "properties": {
        "grades": {
          "type": "nested",
          "properties": {
            "subject": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "score": {
              "type": "float"
            }
          }
        },...
      }
    }
  }
}

对于计数范围,我创建了一个类似于以下内容的查询:

GET student-grades/_search
{
  "aggs": {
    "nestedAgg": {
      "nested": {
        "path": "grades"
      },
      "aggs": {
        "gradeRanges": {
          "range": {
            "field": "grades.score",
            "ranges": [
              {
                "key": "range1",
                "to": 35.01
              },
              {
                "key": "range2",
                "from": 35.01,
                "to": 50.01
              },
              {
                "key": "range3",
                "from": 50.01,
                "to": 60.01
              },
              {
                "key": "range4",
                "from": 60.01,
                "to": 70.01
              },
              {
                "key": "range5",
                "from": 70.01
              }
            ]
          },
          "aggs": {
            "perDoc": {
              "top_hits": {
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

但是,它只给出了所有文档的范围列表。主题的数量不是固定的,所以我不能在top_hits中设置一个随机的大小。那么,我如何才能得到每个文档的所有范围呢?(我是elasticsearch的新手,所以我不知道它的所有功能。

pes8fvy9

pes8fvy91#

我使用了一个简单的脚本来解决这个问题。

GET grades/_search
{
  "script_fields": {
    "gradeRanges": {
      "script": {
        "source": """
            List gradeList = doc['grades.score'];
            List gradeRanges= new ArrayList();
           
            for(int i=0; i<5; i++) {
              gradeRanges.add(0);
            }
           
            for(int i=0; i<gradeList.length; i++) {
              if(gradeList[i]<=35.0) {
                gradeRanges[0]++;
              } else if(gradeList[i]<=50.0) {
                gradeRanges[1]++;
              } else if(gradeList[i]<=60.0) {
                gradeRanges[2]++;
              } else if(gradeList[i]<=70.0) {
                gradeRanges[3]++;
              } else {
                gradeRanges[4]++;
              }
            }
            return gradeRanges;
            """
        }
      }
    },
    "size": 100
  }

这将为每个文档提供单独的级别范围,如下所示:

{
  "took": 38,
  "timed_out": false,
  "_shards": {
    "total": 2,
    "successful": 2,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 12,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "grades",
        "_id": "11",
        "_score": 1,
        "fields": {
          "gradeRanges": [
            0,
            2,
            0,
            3,
            1
          ]
        }
      },
      {
        "_index": "grades",
        "_id": "12",
        "_score": 1,
        "fields": {
          "gradeRanges": [
            0,
            1,
            0,
            1,
            1
          ]
        }
      }
    ]
  }
}

相关问题