Elastic:doc[‘field‘].value与params._source[‘field‘]的区别;doc循环依赖问题

简介: 今天有同学问到doc['field'].value与params._source['field']用法的区别,起因在于下述的一道题的解法上,下面详细讲述下我的看法

0.引用

今天有同学问到doc['field'].value与params._source['field']用法的区别,起因在于下述的一道题的解法上,下面详细讲述下我的看法
【有错望指出,看完如果有表述的不清楚,或者不明白的,也请告诉我,我们一起完善这个知识点】

1 题目

题目是要求根据现有字段,利用runtime mapping计算原字段的值
这是索引mapping

{
  "dur_log-1" : {
    "mappings" : {
      "properties" : {
        "browser" : {
          "type" : "keyword"
        },
        "duration" : {
          "type" : "double"
        },
        "timestamp" : {
          "type" : "date",
          "format" : "yyyy-MM-dd HH:mm:ss"
        }
      }
    }
  }
}

以下是习题答案:

duration字段的值是当browser字段为‘Firefox’时就除以1000。
GET dur_log-1/_search
{
  "runtime_mappings": {
    "duration": {
      "type": "double",
      "script": {
        "source": """
        if(doc['browser'].value == "Firefox"){ 
          emit(params._source['duration'] / 1000.0);
        } else {
          emit(params._source['duration']); 
        }
        """
      }
    }
  },
  "size": 0,
  "aggs": {
    "terms": {
      "terms": {
        "field": "browser"
      },
      "aggs": {
        "average duration": {
          "avg": {
            "field": "duration"
          }
        }
      }
    }
  }
}

这个答案本身没有什么问题,但大家知道painless中引用字段的方法有两种doc和params。这里面引用duration时用了params,但是当我们把这里的引用改为doc时就会发现出现问题了

报错了,错误原因是Cyclic dependency detected while resolving runtime fields: duration -> duration。也就是说产生循环依赖了。这是为什么呢?引用同一个变量,params就不报错,而doc为什么就报错了呢?
在这里插入图片描述

2 规避方案

在阐明问题原因之前,我先说明一下如何规避这种问题,如果你要给已有字段赋值,并且要调用这个字段本身,那就使用params取值,其他的场景只要字段类型为简单值的都可以用doc

什么是简单值?见下述解释

3 问题原因

那么接下来我们就来分析问题的原因,为什么放到最后讲,是因为以下原因仅仅基于本人查阅资料后的推测,并没有实验数据或官方材料支撑这个想法,所以仅供参考

doc和params的区别

首先我们要理解doc和params的区别:

doc是加载到内存中,直接从内存中获取对象的。所以它的显著特点就是快!doc另外一个显著特点就是只能访问简单字段值,什么是简单字段值?根据官方的描述:
```
Doc-values can only return "simple" field values like numbers, dates, geo- points, terms, etc, or arrays of these values if the field is multi-valued. It cannot return JSON objects.
```

即数字、日期、地理点、术语等或者这些值的数组,所以doc不支持json对象

params是从磁盘中获取的,每次都要从磁盘取一次,所以速度相对较慢。所以一般情况下,我们更加推荐使用doc

原因推测

基于以上基础,我们知道doc是直接从内存获取,比如说我们要赋值duration的内存地址为a,而引用的doc['duration']也为a,也就是说如果用doc的获取duration,就相当于我引用我自己来定义我自己,如下图所示,没有尽头。这也就产生了循环依赖。
在这里插入图片描述
而params为什么可以呢?因为params是从磁盘获取后再加载到内存的,所以每次的内存地址都是新的,因此也就没有了循环依赖的问题。

以上就是个人对这个问题的理解和推测,不具备真实性。

目录
相关文章
|
6月前
|
存储 JSON 数据格式
数据集加载时报错'dict' object has no attribute 'requests‘
数据集加载时报错'dict' object has no attribute 'requests‘
118 5
|
21天前
|
索引
Elasticsearch exception [type=illegal_argument_exception, reason=index [.1] is the write index for data stream [slowlog] and cannot be deleted]
在 Elasticsearch 中,你尝试删除的索引是一个数据流(data stream)的一部分,而且是数据流的写入索引(write index),因此无法直接删除它。为了解决这个问题,你可以按照以下步骤进行操作:
|
1月前
|
SQL 关系型数据库 MySQL
mysql查询语句的访问方法const、ref、ref_or_null、range、index、all
mysql查询语句的访问方法const、ref、ref_or_null、range、index、all
|
7月前
|
Java
【ES异常】mapper [sortNum] of different type, current_type [long], merged_type [keyword]
【ES异常】mapper [sortNum] of different type, current_type [long], merged_type [keyword]
52 0
|
5月前
|
Scala
【已解决】Specifying keys via field positions is only valid for tuple data types. Type: GenericType<scala
【已解决】Specifying keys via field positions is only valid for tuple data types. Type: GenericType<scala
27 0
|
6月前
|
JSON 小程序 API
小程序踩坑-Setting data field "list" to undefined is invalid.
小程序踩坑-Setting data field "list" to undefined is invalid.
143 0
|
9月前
|
JavaScript
vue 渲染列表报错Avoid using non-primitive value as key, use string/number value instead. found in
vue 渲染列表报错Avoid using non-primitive value as key, use string/number value instead. found in
43 0
对‘avformat_find_stream_info’未定义的引用、to the PKG_CONFIG_PATH environment variable
对‘avformat_find_stream_info’未定义的引用、to the PKG_CONFIG_PATH environment variable
66 0
|
数据采集 Python
'str' object has no attribute 'get' 错误解决方案
'str' object has no attribute 'get' 错误解决方案
ES中的Multi_match深入解读:best_fields、most_fields、cross_fields用法一览
ES中的Multi_match深入解读:best_fields、most_fields、cross_fields用法一览
ES中的Multi_match深入解读:best_fields、most_fields、cross_fields用法一览