如何在elasticsearch中获取文档大小(以字节为单位)

p4rjhz4m  于 2021-06-14  发布在  ElasticSearch
关注(0)|答案(2)|浏览(1762)

我对elasticsearch是个新手。我需要得到文档大小的查询结果。
example:-- this is a document. (19bytes). this is also a document. (24bytes) content:{"a":"this is a document", "b":"this is also a document"}(53bytes) 当我在es中查询文档时。我将得到上述文件作为结果。所以,两个文档的大小都是32字节。我需要elasticsearch中的32字节作为结果。

14ifxucb

14ifxucb1#

无法通过api获取elasticsearch文档大小。原因是索引到elasticsearch的文档在索引中的大小不同,这取决于您是否存储全部、索引哪些字段以及这些字段的Map类型、文档值等等。elasticsearch还使用重复数据消除和其他压缩方法,因此索引大小与其包含的原始文档没有线性关系。
解决这个问题的一种方法是在索引文档之前预先计算文档大小,并将其作为另一个字段添加到文档中,即doc\u size字段。然后可以查询这个计算字段,并对其运行聚合。
但是请注意,正如我上面所说的,这并不代表索引的大小,可能是完全错误的-例如,如果所有文档都包含一个具有相同值的非常长的文本字段,那么elasticsearch将只存储该长的值一次并引用它,因此索引大小将小得多。

5anewei6

5anewei62#

您的文档是否只包含一个字段?我不确定这是你想要的100%,但一般来说,你可以计算字段的长度,要么与文档一起存储,要么在查询时计算(但这是一个缓慢的操作,如果可能的话,我会避免)。
下面是一个测试文档和字段长度计算的示例:

PUT test/_doc/1
{
  "content": "this is a document."
}

POST test/_update_by_query
{
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "content_length"
          }
        }
      ]
    }
  },
  "script": {
    "source": """ 
if(ctx._source.containsKey("content")) {
  ctx._source.content_length = ctx._source.content.length();
} else {
  ctx._source.content_length = 0;
}
"""
  }
}

GET test/_search

查询结果如下:

{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "content" : "this is a document.",
          "content_length" : 19
        }
      }
    ]
  }
}

顺便说一句,有19个字符(包括空格和点在这一个)。如果你想排除这些,你必须给脚本添加更多的逻辑。顺便说一句,我会小心使用字节,因为utf8可能会在每个字符中使用多个字节(比如 höhe )而这个剧本实际上只是在数角色。
然后您可以在查询和聚合中轻松地使用长度。
如果要计算合并的所有子文档的大小,请使用以下命令:

PUT test/_doc/2
{
  "content": {
    "a": "this is a document",
    "b": "this is also a document"
  }
}

POST test/_update_by_query
{
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "content_length"
          }
        }
      ]
    }
  },
  "script": {
    "source": """
if(ctx._source.containsKey("content")) {
  ctx._source.content_length = 0;
  for (item in ctx._source.content.entrySet()) {
    ctx._source.content_length += item.getValue().length();
  }
}
"""
  }
}

GET test/_search

请注意 content 可以是文本类型,也可以有子文档,但不能混用。

相关问题