繁体   English   中英

elasticsearch 中按文档的子文档字段的平均值

[英]Average of subdocument fields by document in elasticsearch

我有一个 elasticsearch 映射,它代表具有将他们的标记表示为对象数组的属性的学生:

properties: {
  name: { type: "text" },
  /* ... */
  marks: {
    properties: {
      value: { type: "float" }
    }
  }
}

基于此映射,文档以这种形式存储:

"hits" : [{
  "_index" : "students",
  "_type" : "_doc",
  "_id" : "...",
  "_score" : 1.0,
  "_source" : {
    "name" : "John Doe",
    "marks" : [
      {
        "_id" : "...",
        "value" : 4
      },
      {
        "_id" : "...",
        "value" : 0
      }
    ]
  }
}, 
{
  "_index" : "students",
  "_type" : "_doc",
  "_id" : "...",
  "_score" : 1.0,
  "_source" : {
    "name" : "Jane Doe",
    "marks" : [
      {
        "_id" : "...",
        "value" : 5
      },
      {
        "_id" : "...",
        "value" : 4
      }
    ]
  }
}, /* ... */]

每个学生都有很多分数。 我想在 elasticsearch 的结果中得到学生标记值的平均值(因此通过弹性搜索中索引的文档)。

我尝试了一个聚合:

"aggs": {
  "avg_mark": {
    "avg": { "field": "marks.value" }
  }
}

但我得到了所有学生的平均值:

aggregations: { avg_mark: { value: 3.25 } }

然后我尝试了排序:

"sort": [{
  "marks.value": {
    "order": "desc",
    "mode": "avg"
  }
}]

学生的平均成绩很好,但是:

  • 它对我的结果进行排序,我并不总是需要它
  • 它将平均结果存储在一个没有键的数组中来检索它。 这不是我需要的,因为排序属性顺序可能会根据用户搜索而改变。
"hits" : [{
  "_index" : "students",
  "_type" : "_doc",
  "_id" : "...",
  "_score" : 1.0,
  "_source" : {
    "name" : "John Doe",
    "marks" : [
      {
        "_id" : "...",
        "value" : 4
      },
      {
        "_id" : "...",
        "value" : 0
      }
    ]
  },
  "sort" : [ 2.0 ]
}, 
{
  "_index" : "students",
  "_type" : "_doc",
  "_id" : "...",
  "_score" : 1.0,
  "_source" : {
    "name" : "Jane Doe",
    "marks" : [
      {
        "_id" : "...",
        "value" : 5
      },
      {
        "_id" : "...",
        "value" : 4
      }
    ]
  },
  "sort" : [ 4.5 ]
}, /* ... */]

这个排序数组可以是[ 4.5, value_b, value_c, ... ][value_b, value_c, 4.5 ]具体取决于排序搜索请求属性。

我也尝试过使用嵌套类型但没有成功。

如何在不对结果进行排序并且轻松检索结果的情况下获得文档/学生的平均值?

先感谢您。

您的第一次尝试是朝着正确方向迈出的一步 - 只需确保在计算平均分数之前按学生姓名分组:

GET students/_search
{ 
  "size": 0,
  "aggs": {
    "by_student": {
      "terms": {
        "field": "name.keyword",
        "size": 10
      },
      "aggs": {
        "avg_mark": {
          "avg": {
            "field": "marks.value"
          }
        }
      }
    }
  }
}

.keyword字段后缀来自这个稍微调整的映射:

PUT students
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"     <--
          }
        }
      },
      "marks": {
        "properties": {
          "value": {
            "type": "float"
          }
        }
      }
    }
  }
}

顺便说一句——如果您想将搜索范围缩小到只有少数学生,只需包含一个顶级查询,如下所示:

{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "name.keyword": [
              "John Doe",
              "Jane Doe"
            ]
          }
        }
      ]
    }
  },
  "aggs": { ... }
}

然后,聚合将仅考虑过滤的文档集。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM