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

举报
wu@55555 发表于 2022/11/17 22:04:58 2022/11/17
【摘要】 今天有同学问到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是从磁盘获取后再加载到内存的,所以每次的内存地址都是新的,因此也就没有了循环依赖的问题。

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。