【Elastic Engineering】Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)

作者:刘晓国


在很多的设计中,我们所采集的数据来自不同的数据源,从而导致数据字段名称的不一致。如果,我们在一开始就遵循 Elastic Common Schema,那么我们就不会有任何的问题。但是在实际的生产环境中,有可能在一开始我们就没有这么做,那我们该如何解决这个问题呢?比如我们有如下的两个数据:

POST logs_server1/_doc/
{
  "level": "info"
}
POST logs_server2/_doc/
{
  "log_level": "info"
}

在上面的两个数据是来自两个不同的服务器,在当时设计的时候,表示 log 的级别分别用了不同的字段:level 及 log_level。显然这两个不同的字段不便于我们统计数据。安装 Elastic Common Schemaimage.png的要求,正确的字段应该是 log.level。那么我们在不改变原有的 log 的设计基础之上,该如何实现符号 ECS 规范的 mapping 呢?


在之前的文章 “Elasticsearch : alias 数据类型”,我已经讲述了 alias 的数据类型。在今天的文章中,我来详细描述如何使用 alias 来解决这个问题。


准备数据

我们安装上面所显示的那样,把两个数据导入到 Elasticsearchimage.png 中:

POST logs_server1/_doc/
{
  "level": "info"
}
POST logs_server2/_doc/
{
  "log_level": "info"
}

我们可以通过如下的命令来检查一下这两个索引的 mapping:

GET logs_server1/_mapping
{
  "logs_server1" : {
    "mappings" : {
      "properties" : {
        "level" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}
GET logs_server2/_mapping
{
  "logs_server2" : {
    "mappings" : {
      "properties" : {
        "log_level" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

显然上面的两个索引的 mapping 都是不一样的。


如果我们想统计一下 logs 按照级别 level 进行统计的话,我们只能按照如下的方法来进行:

GET logs_server*/_search
{
  "size": 0,
  "aggs": {
    "levels": {
      "terms": {
        "script": {
          "source": """
             if (doc.containsKey('level.keyword')) {
               return doc['level.keyword'].value
             } else {
               return doc['log_level.keyword'].value
             }
          """
        }
      }
    }
  }
}

在上面,我使用了 script 来进行统计。在上面脚本中的 doc,其实就是 doc_values。如果大家对这个 doc 的方法不是很熟悉的话,请参阅我之前的文章 “Elasticsearch:Painless 编程调试”。我们可以使用如下的方法:

GET logs_server*/_search
{
  "size": 0,
  "aggs": {
    "levels": {
      "terms": {
        "script": {
          "source": """
            Debug.explain(doc)
          """
        }
      }
    }
  }
}

上面的查询会导致如下的错误信息:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "script_exception",
        "reason" : "runtime error",
        "to_string" : "org.elasticsearch.search.lookup.LeafDocLookup@6814c133",
        "java_class" : "org.elasticsearch.search.lookup.LeafDocLookup",
        "script_stack" : [
          "Debug.explain(doc)\n          ",
          "              ^---- HERE"
        ],
        "script" : "\n            Debug.explain(doc)\n          ",
        "lang" : "painless",
        "position" : {
          "offset" : 27,
          "start" : 13,
          "end" : 42
        }
      },
      {
        "type" : "script_exception",
        "reason" : "runtime error",
        "to_string" : "org.elasticsearch.search.lookup.LeafDocLookup@6454e4d",
        "java_class" : "org.elasticsearch.search.lookup.LeafDocLookup",
        "script_stack" : [
          "Debug.explain(doc)\n          ",
          "              ^---- HERE"
        ],
        "script" : "\n            Debug.explain(doc)\n          ",
        "lang" : "painless",
        "position" : {
          "offset" : 27,
          "start" : 13,
          "end" : 42
        }
      }
    ],
    "type" : "search_phase_execution_exception",
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "logs_server1",
        "node" : "2bFyWe-OSpeW98xsZMrjng",
        "reason" : {
          "type" : "script_exception",
          "reason" : "runtime error",
          "to_string" : "org.elasticsearch.search.lookup.LeafDocLookup@6814c133",
          "java_class" : "org.elasticsearch.search.lookup.LeafDocLookup",
          "script_stack" : [
            "Debug.explain(doc)\n          ",
            "              ^---- HERE"
          ],
          "script" : "\n            Debug.explain(doc)\n          ",
          "lang" : "painless",
          "position" : {
            "offset" : 27,
            "start" : 13,
            "end" : 42
          },
          "caused_by" : {
            "type" : "painless_explain_error",
            "reason" : null
          }
        }
      },
      {
        "shard" : 0,
        "index" : "logs_server2",
        "node" : "2bFyWe-OSpeW98xsZMrjng",
        "reason" : {
          "type" : "script_exception",
          "reason" : "runtime error",
          "to_string" : "org.elasticsearch.search.lookup.LeafDocLookup@6454e4d",
          "java_class" : "org.elasticsearch.search.lookup.LeafDocLookup",
          "script_stack" : [
            "Debug.explain(doc)\n          ",
            "              ^---- HERE"
          ],
          "script" : "\n            Debug.explain(doc)\n          ",
          "lang" : "painless",
          "position" : {
            "offset" : 27,
            "start" : 13,
            "end" : 42
          },
          "caused_by" : {
            "type" : "painless_explain_error",
            "reason" : null
          }
        }
      }
    ]
  },
  "status" : 400
}

从上面我们可以看出来 doc 是一个 org.elasticsearch.search.lookup.LeafDocLookup 类型的数据。我们可以通过谷歌搜索来找到这个数据类型的所有方法。其中 containsKey 的描述在链接 https://www.javadoc.io/doc/org.elasticsearch/elasticsearch/6.0.1/org/elasticsearch/search/lookup/LeafDocLookup.html


上面按照脚本的方法来进行统计,有一个很大的缺点:每次在统计的时候都需要进行计算,如果有大量的数据的话,这样的计算量会很大。那么有没有一种比较简单的方法呢?


使用 alias 数据类型把数据归一化


我们参照之前的文章 “Elasticsearch : alias 数据类型”,我们可以把 level 都按照 ECS 的要求,对应于 log.level。对上面的两个索引做如下的操作:

PUT logs_server1/_mapping
{
  "properties": {
    "log": {
      "properties": {
        "level": {
          "type": "alias",
          "path": "level.keyword"
        }
      }
    }
  }
}

经过上面的操作后,logs_sever1 的 mapping 如下:

GET logs_server1/_mapping
{
  "logs_server1" : {
    "mappings" : {
      "properties" : {
        "level" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "log" : {
          "properties" : {
            "level" : {
              "type" : "alias",
              "path" : "level.keyword"
            }
          }
        }
      }
    }
  }
}

同样地,我们对 logs_server2 也进行同样的操作:

PUT logs_server2/_mapping
{
  "properties": {
    "log": {
      "properties": {
        "level": {
          "type": "alias",
          "path": "log_level.keyword"
        }
      }
    }
  }
}

那么 logs_server2 的 mapping 变为:

{
  "logs_server2" : {
    "mappings" : {
      "properties" : {
        "log" : {
          "properties" : {
            "level" : {
              "type" : "alias",
              "path" : "log_level.keyword"
            }
          }
        },
        "log_level" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

经过上面的改造之后,我们可以看出来,这两个索引的 mapping 都有一个共同的字段 log.level,尽管它们是 alias 数据类型。


我们很容易使用如下的方法来对 level 进行统计了:

GET  logs_server*/_search
{
  "size": 0,
  "aggs": {
    "levels": {
      "terms": {
        "field": "log.level",
        "size": 10
      }
    }
  }
}

现在显然比之前的 script 来统计数据方便很多了,而且它不需要有大量的计算了。


相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
测试技术 索引
Elasticsearch alias别名管理小结
Elasticsearch alias别名管理小结
257 0
|
API 网络架构 索引
|
弹性计算 索引
【Elastic Engineering】Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)
Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)
347 0
【Elastic Engineering】Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)
|
弹性计算 API 索引
|
4月前
|
JSON 安全 数据可视化
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
Kibana 是 Elastic Stack(原 ELK Stack)中的核心数据可视化工具,主要与 Elasticsearch 配合使用,提供强大的数据探索、分析和展示功能。elasticsearch安装在windows上一般是zip文件,解压到对应目录。文件,elasticsearch8.x以上版本是自动开启安全认证的。kibana安装在windows上一般是zip文件,解压到对应目录。elasticsearch的默认端口是9200,访问。默认用户是elastic,密码需要重置。
2065 0
|
5月前
|
安全 Java Linux
Linux安装Elasticsearch详细教程
Linux安装Elasticsearch详细教程
877 1
|
10月前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
403 5
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
11月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
1074 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。

相关产品

  • 检索分析服务 Elasticsearch版