ElasticSearch学习随笔之嵌套操作

ElasticSearch

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 调用操作。


文章目录

  • ElasticSearch
  • 前言
  • 一、嵌套数据类型
  • 二、添加数据
    • 2.1 构建嵌套 mapping 映射
    • 2.2 添加测试数据
    • 2.3 添加mapping之外的数据
    • 2.4 查看添加的数据
  • 三、嵌套操作
    • 3.1 按照嵌套类型查询
    • 3.2 按照嵌套类型排序
    • 3.3 嵌套类型分组统计
    • 3.4 修改嵌套类型字段值
  • 四、总结


前言

今天工作中遇到嵌套类型的数据,查询总是查询不到,一开始感到疑惑,为啥 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 的版本写的。

ElasticSearch学习随笔之嵌套操作_第1张图片

三、嵌套操作

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": "华为手机"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

搜索结果:
ElasticSearch学习随笔之嵌套操作_第2张图片

从搜索结果可以看到,进准搜索到了华为手机这个产品,当然,也可以模糊查询, 就像 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"
      }
    }
  ]
}

排序结果如下:
ElasticSearch学习随笔之嵌套操作_第3张图片
注意: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个。

ElasticSearch学习随笔之嵌套操作_第4张图片
更复杂的分组统计可到官网查看,工作中大部分用到的以上的风阻统计就可以满足了,若有更复杂的,则继续在及过上过滤和统计。

3.4 修改嵌套类型字段值

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

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

修改结果:
ElasticSearch学习随笔之嵌套操作_第5张图片

四、总结

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

你可能感兴趣的:(JAVA后台,ElasticSearch,搜索引擎,elasticsearch,搜索引擎)