ElasticSearch学习随笔之嵌套操作

ElasticSearch

1、ElasticSearch学习随笔之基础介绍
2、ElasticSearch学习随笔之简单操作
3、ElasticSearch学习随笔之java api 操作
4、ElasticSearch学习随笔之SpringBoot Starter 操作
5、ElasticSearch学习随笔之嵌套操作
6、ElasticSearch学习随笔之分词算法
7、ElasticSearch学习随笔之高级检索
8、ELK技术栈介绍
9、Logstash部署与使用
10、ElasticSearch 7.x 版本使用 BulkProcessor 实现批量添加数据
11、ElasticSearch 8.x 弃用了 High Level REST Client,移除了 Java Transport Client,推荐使用 Elasticsearch Java API
12、ElasticSearch 8.x 使用 snapshot(快照)进行数据迁移
13、ElasticSearch 8.x 版本如何使用 SearchRequestBuilder 检索
14、ElasticSearch 8.x 使用 High Level Client 以 HTTPS 方式链接,SSL 证书、主机名验证器 各是什么,如何忽略
15、ElasticSearch 8.x 创建父子文档,用Join类型字段以及用has_child、has_parent 检索
16、ElasticSearch如何提高写入效率【面试题,面道既学到】

ElasticSearch,创始人 Shay Banon(谢巴农)
本文主要讲解ElasticSearch 基础操作,Kibana 以及 java api 调用操作。



前言

今天工作中遇到嵌套类型的数据,查询总是查询不到,一开始感到疑惑,为啥 match_all 的时候有,但是精确操作就查不到,查了半天才发现,嵌套操作有点区别。
本文主要对ElasticSearch嵌套(Nested) 操作,以便上手 用 ElasticSearch

一、嵌套数据类型

在基础篇中介绍了一些 ES 的数据类型,比如:Text、keyword、byte、string 等,这些类型的数据操作起来比较容易,在 ES简单操作中介绍了,不过 ES 有些数据结构上稍微复杂一点,使用嵌套类型就比较明显和容易维护。
比如说一个子弹是 productName ,但是这个字段有中英文、id、raw等不同的值,如果这些字段用 string 类型存储,那字段就会很多,那么我们可以用嵌套类型的数据结构,这样维护起来就方便点,不过需要用嵌套的方式进行查询。
类似这样:

{
	"productName":{
		"cn":"手机",
		"en":"iphone",
		"id": 100,
		"raw":"苹果手机"
	}
}

二、添加数据

2.1 构建嵌套 mapping 映射

下面的 mapping 映射中,相当于 solr 的schema 定义固定的数据结构,我们也可以增加其他数据类型,不过在创建了映射之后就只能按照 mapping 来存放数据和操作。
productName 一个嵌套(nested)类型来存放的,在查询,排序等操作的时候就需要按照嵌套来操作。

PUT productinfo
{
  "mappings": {
    "properties": {
      "productName":{
        "type": "nested",
        "properties": {
          "cn":{
            "type":"keyword",
            "store":true
          },
          "en":{
            "type":"keyword",
            "store":true
          },
          "raw":{
            "type":"keyword",
            "store":true
          },
          "id":{
            "type":"keyword",
            "store":true
          }
        }
      },
      "productSize":{
        "type": "keyword",
        "store": true
      },
      "productDesc":{
        "type": "text",
        "store": true
      }
    }
  }
}

2.2 添加测试数据

我们用 bulk 来批量添加数据,按照 mapping 添加数据。

POST productinfo/_bulk
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"苹果手机11","en":"iphone11","id":"1001","raw":"手机"},"productSize":16,"productDesc":"打电话,微信,拍照"}
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"苹果手机12","en":"iphone12","id":"1002","raw":"手机"},"productSize":17,"productDesc":"打电话,微信,拍照3000像素"}
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"小米手机","en":"xiaomi","id":"1003","raw":"手机"},"productSize":15,"productDesc":"打电话,微信,拍照,5G上网"}
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"华为手机","en":"huawei","id":"1004","raw":"手机"},"productSize":14,"productDesc":"打电话,微信,拍照,打游戏"}

2.3 添加mapping之外的数据

也可以添加没有 mapping 的字段,比如 commonProductName 就没有 mapping,不过查询操作也不用按照嵌套来查询。

{"index":{"_index":"productinfo"}}
{"commonProductName":"笔记本电脑","productSize":14,"productDesc":"上网,工作,打游戏,学习,看电影"}
{"index":{"_index":"productinfo"}}
{"commonProductName":"液晶屏电视","productSize":60,"productDesc":"上网,看电影,追剧"}

2.4 查看添加的数据

用 match_all 来查看全部的数据。
这里有个不同之处,就是 es7 之前的版本,需要指定 dataType 类型,就像在 es 基础操作篇(见文档开头)那样,因为 基础篇是用 6.x 的版本写的。

查看添加的数据

三、嵌套操作

3.1 按照嵌套类型查询

说明:在搜索嵌套类型的字段的时候,需要指定 path 参数,来告诉 es 从 productName 字段下的 内嵌字段用 match、term、multi_match 等来搜索。
比如说现在要按照 productName 来搜索一个产品,搜索 “华为手机” 库里面有几个,搜索如下:

POST productinfo/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "productName",
            "query": {
              "bool": {
                "should": [
                  {
                    "match": {
                      "productName.cn": "华为手机"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

搜索结果:
搜索华为手机

从搜索结果可以看到,进准搜索到了华为手机这个产品,当然,也可以模糊查询, 就像 es 操作的基础篇那样 (见文档开头系列目录),或者搜索 cn , en 另个字段,那么外面就是 should (or) 的关系 。

3.2 按照嵌套类型排序

下面按照 productName.cn 进行模糊搜索出来了两条数据,然后按照 productName.id 降序排序。

POST productinfo/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "productName",
            "query": {
              "bool": {
                "should": [
                  {
                    "wildcard": {
                      "productName.cn": "*苹果*"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "productName.id": {
        "order": "desc",
        "nested_path": "productName"
      }
    }
  ]
}

排序结果如下:
通过productName.id排序
注意:es 提示了一行红字,意思是说 nested_path 已经弃用了,被 nested 替代了,不过我感觉还是用起来挺方便的。

那么官方推荐应该怎么写呢?如下:
下面的写法基本不变,不过坑的就是,nested 居然不提示,但是生效

POST productinfo/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "productName",
            "query": {
              "bool": {
                "should": [
                  {
                    "wildcard": {
                      "productName.cn": "*苹果*"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "productName.id": {
        "order": "desc",
        "nested":{
          "path":"productName"
        }
      }
    }
  ]
}

3.3 嵌套类型分组统计

按照 productName 和 productName.cn 进行分组统计,如下:

POST productinfo/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "productName_count": {
      "nested": {
        "path": "productName"
      },
      "aggs": {
        "cn_count": {
          "terms": {
            "field": "productName.cn",
            "size": 10
          }
        }
      }
    }
  }
}

执行结果如下:

统计出来,productName.cn 字段,有 3 个苹果11, 华为、小米、苹果12 各 1个。

分组统计
更复杂的分组统计可到官网查看,工作中大部分用到的以上的风阻统计就可以满足了,若有更复杂的,则继续在及过上过滤和统计。

3.4 修改嵌套类型字段值

修改按照 PUT 操作,带上 _id 即可修改。

PUT productinfo/_bulk
{"index":{"_index":"productinfo", "_id":"ZU8ga4MBZkN8aRGpIqAA"}}
{"productName":{"cn":"苹果手机12","en":"iphone11","id":"1008","raw":"手机"},"productSize":16,"productDesc":"打电话,微信,拍照"}

修改结果:
修改成功

四、总结

ElasticSearch 现在比较流行的全文搜索引擎,平时工作中用到的都是基础类型,有些情况下用到了嵌套类型字段,虽然数据在架构师清晰了,但是操作起来变的稍微复杂点,看情况使用吧。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值