1、ElasticSearch学习随笔之基础介绍
2、ElasticSearch学习随笔之简单操作
3、ElasticSearch学习随笔之java api 操作
4、ElasticSearch学习随笔之SpringBoot Starter 操作
5、ElasticSearch学习随笔之嵌套操作
6、ElasticSearch学习随笔之分词算法
7、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":"苹果手机"
}
}
下面的 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
}
}
}
}
我们用 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":"打电话,微信,拍照,打游戏"}
也可以添加没有 mapping 的字段,比如 commonProductName 就没有 mapping,不过查询操作也不用按照嵌套来查询。
{"index":{"_index":"productinfo"}}
{"commonProductName":"笔记本电脑","productSize":14,"productDesc":"上网,工作,打游戏,学习,看电影"}
{"index":{"_index":"productinfo"}}
{"commonProductName":"液晶屏电视","productSize":60,"productDesc":"上网,看电影,追剧"}
用 match_all 来查看全部的数据。
这里有个不同之处,就是 es7 之前的版本,需要指定 dataType 类型,就像在 es 基础操作篇(见文档开头)那样,因为 基础篇是用 6.x 的版本写的。
说明:在搜索嵌套类型的字段的时候,需要指定 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) 的关系 。
下面按照 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"
}
}
]
}
排序结果如下:
注意: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"
}
}
}
]
}
按照 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个。
更复杂的分组统计可到官网查看,工作中大部分用到的以上的风阻统计就可以满足了,若有更复杂的,则继续在及过上过滤和统计。
修改按照 PUT 操作,带上 _id 即可修改。
PUT productinfo/_bulk
{"index":{"_index":"productinfo", "_id":"ZU8ga4MBZkN8aRGpIqAA"}}
{"productName":{"cn":"苹果手机12","en":"iphone11","id":"1008","raw":"手机"},"productSize":16,"productDesc":"打电话,微信,拍照"}
ElasticSearch 现在比较流行的全文搜索引擎,平时工作中用到的都是基础类型,有些情况下用到了嵌套类型字段,虽然数据在架构师清晰了,但是操作起来变的稍微复杂点,看情况使用吧。