您当前的位置: 首页 >  ar

wu@55555

暂无认证

  • 2浏览

    0关注

    201博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Elastic:针对doc与params的一些思考;doc[‘field‘].value与params._source[‘field‘]的区别;doc循环依赖问题

wu@55555 发布时间:2021-12-01 20:40:10 ,浏览量:2

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是从磁盘获取后再加载到内存的,所以每次的内存地址都是新的,因此也就没有了循环依赖的问题。

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

关注
打赏
1664985904
查看更多评论
立即登录/注册

微信扫码登录

0.0816s