ElasticSearch+集群配置使用最全详解

文章目录

    • 1 概述
        • 1.1 简介
        • 1.2 特点
        • 1.3 lucene与ES区别
        • 1.4 有关概念
    • 2 ES安装
        • 2.1 下载
        • 2.2 安装分词器
        • 2.3 可视化工具kibana安装
    • 3 ES的RESTful风格
        • 3.1 概述
        • 3.2 优点
        • 3.3 示例
    • 4 操作ES
        • 4.1 索引库index的CRUD
            • 4.1.1 添加索引库
            • 4.1.2 查看索引库
            • 4.1.3 修改索引库
            • 4.1.4 删除索引库
        • 4.2 文档document的CRUD
            • 4.2.1 关键字详解
            • 4.2.2 添加文档
            • 4.2.3 查询文档
            • 4.2.4 修改文档
            • 4.2.5 删除文档
        • 4.3 文档的高级查询
            • 4.3.1 批量查询
            • 4.3.2 分页查询及高级搜索
        • 4.4 DSL查询与DSL过滤
        • 4.5 文档的映射
            • 4.5.1 映射字段类型
            • 4.5.2 默认映射
            • 4.5.3 字段映射的常用属性配置列表
            • 4.5.4 添加映射
            • 4.5.5 全局映射
    • 5 ES集群
        • 5.1 概述
            • 5.1.1 集群优点
            • 5.1.2 ES节点类型
            • 5.1.3 最佳方案
        • 5.2 shard及primary/replica shard
        • 5.3 不同数量节点的shard分配
            • 5.3.1 单node环境下创建
            • 5.3.2 两个node环境下创建
            • 5.3.3 扩容极限,性能更优
            • 5.3.4 容错机制
        • 5.4 集群搭建
            • 5.4.1 配置说明
            • 5.4.2 修改配置
            • 5.4.3 连接集群
    • 6 Java操作ES集群
        • 6.1 maven方式导入依赖
        • 6.2 使用工具类连接ES
        • 6.3 文档的CRUD

1 概述

1.1 简介

ElasticSearch是一个基于Lucene的全文搜索服务器。它提供了一个分布式集群,多用户能力的全文搜索引擎 , 基于RESTful web接口 , 以使全文搜索变得简单易用

1.2 特点

  • 分布式全文搜索引擎
  • 可以在在分布式项目或集群中使用
  • 本身支持集群扩展
  • 处理PB级结构化或非结构化数据
  • 简单的RESTful API通信方式
  • 支持各种语言的客户端
  • 基于Lucene封装,使操作简单

1.3 lucene与ES区别

  • lucene只支持java语言,ES支持多种语言
  • lucene不支持分布式,索引目录仅在本地
  • lucene使用复杂
  • lucene只适合小型项目使用

1.4 有关概念

  • cluster:代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。
  • shards:代表索引分片,es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。每个shard都是一个lucene index
  • replica:代表索引副本,es可以设置多个索引的副本,副本的作用一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高es的查询效率,es会自动对搜索请求进行负载均衡。primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。
  • recovery:代表数据恢复或叫数据重新分布,es在有节点加入或退出时会根据机器的负载对索引分片进行重新分配 ; 挂掉的节点重新启动时会先进行本地数据恢复然后再从原来的从节点进行恢复,然后成为新的从节点,原从节点成为主节点。
  • Transport:代表es内部节点或集群与客户端的交互方式,默认内部是使用tcp协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。

ElasticSearch+集群配置使用最全详解_第1张图片

2 ES安装

2.1 下载

下载地址
运行 %ES_HOME%\bin\elasticsearch.bat即可运行ES服务器
输入url http://localhost:9200/

2.2 安装分词器

在启动ES前将分词器解压至plugins文件夹下

  • 例:
    ES的IK分词器插件源码地址:https://github.com/medcl/elasticsearch-analysis-ik 解压elasticsearch-analysis-ik-5.2.2.zip文件
  • 测试
POST _analyze
{
  "analyzer":"ik_smart",
  "text":"《新闻联播》播发国际锐评:打“香港牌”牵制中国的图谋必败无疑"
}

IK分词器指定:ik_smart(智能模式) ; ik_max_word(最大细粒度)

2.3 可视化工具kibana安装

下载地址
解压并编辑config/kibana.yml,设置elasticsearch.url的host为已启动的ES(一般默认9200)
启动 打开bin\kibana.bat 访问地址http://localhost:5601

  • Discover:可视化查询分析器
  • Visualize:统计分析图表
  • Dashboard:自定义主面板(添加图表)
  • Timelion:Timelion是一个kibana时间序列展示组件(暂时不用)
  • Dev Tools :Console(同CURL/POSTER,操作ES代码工具,拥有代码提示,很方便)
  • Management:管理索引库(index)、已保存的搜索和可视化结果(save
    objects)、设置 kibana 服务器属性。

3 ES的RESTful风格

3.1 概述

RESTful是一种面向资源的架构风格,可以简单理解为:使用URL定位资源,用HTTP动词(GET,POST,DELETE,PUT)描述操作。

3.2 优点

  • 透明性,暴露资源存在。
  • 充分利用 HTTP 协议本身语义。
  • 无状态,这点非常重要。在调用一个接口(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前- - 状态,极大的降低了复杂度。
  • HTTP 本身提供了丰富的内容协商手段,无论是缓存,还是资源修改的乐观并发控制,都可以以业务无关的中间件来实现。

3.3 示例

  • 获取资源 GET /user/1 => 获取id为1的用户
    GET /users=> 获取用户列表
  • 添加数据 PUT /user => 添加用户 数据:{“id”:“1”,“name”:“cc”}
  • 修改 POST /user 数据{“id”:“1”,“name”:“cc”}
  • 删除资源 DELELE /user/1 => 删除id为1的用户
  • 4 操作ES

4.1 索引库index的CRUD

4.1.1 添加索引库
PUT crm
{
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  }
}
4.1.2 查看索引库
  • 查看所有索引库
GET _cat/indices?v
  • 查看指定索引库
GET _cat/indices/crm?v
4.1.3 修改索引库

通过删除后再次添加

4.1.4 删除索引库
DELETE crm

4.2 文档document的CRUD

4.2.1 关键字详解
  • _index 索引库 --> crm
  • _type 类型 --> t_employee
  • _document 文档 --> employee对象
  • _id --> 文档的id 一般与数据的id一致
  • _filed 字段 --> username字段
  • _source -->文档的原始数据,我们保存的数据就在这里
  • _all --> 所有字段的连接字符串
  • metadata --> 文档元数据,初始的一些数据
4.2.2 添加文档
PUT crm/employee/1
{
  "id":1,
  "name":"cc",
  "sex":true
}

如不指定路径上的id,ES会自动生成一个id字符串

4.2.3 查询文档
  • 查询所有索引库/指定索引库的所有文档 在后面加上_search
  • 查询指定的文档的全部字段
GET crm/employee/1
  • 查询指定文档的指定字段
GET crm/employee/1?_source=name,sex
  • 查询所有文档
GET crm/employee/_search
4.2.4 修改文档
  • 整体修改
    操作语法相当于添加
PUT crm/employee/2
{
  "id":2,
  "name":"aabbcc",
  "sex":true
}
  • 局部修改
POST crm/employee/2/_update
{
  "doc": {
    "sex":false
  }
}
4.2.5 删除文档
DELETE crm/employee/2

4.3 文档的高级查询

4.3.1 批量查询
  • 不同索引库批量查询
GET _mget
 {
   "docs":[
    {
      "_index":"crm",
      "_type":"employee",
      "_id":"1"
    },{
      "_index":"cms",
      "_type":"user",
      "_id":"1"
    }
   ]
 }
  • 相同索引库相同类型查询
 GET crm/employee/_mget
 {
   "ids":["1","2"]
 }
4.3.2 分页查询及高级搜索
GET crm/user/_search?q=age:17&size=2&from=2&sort=id:desc&_source=id,username

此方式不推荐,因条件过多,拼起来较麻烦,后面会使用下面的方式.

4.4 DSL查询与DSL过滤

DSL查询相当于模糊查询;DSL过滤相当于精确匹配;
ES底层优先使用DSL过滤再使用DSL查询,以达到高效目的;
一般我们会将两者进行结合起来使用:

GET crm/employee/_search
{
  "query":{
      "bool": {
        "must": [
          {"match": {
            "name": "carry"
          }}
        ],
        "filter": [{
          "term": {
            "sex": true
          }},
          {
            "range":{
              "id":{
                  "gte":1,
                  "lte":7
              }
          }
        }]
      }
  },
  "from": 0,
  "size": 10,
  "_source": ["name","sex"],
  "sort": [{"id": "desc"}]
}

关键字 :

  • bool : 组合查询 , 包含了 DSL查询和DSL过滤
  • must : 必须匹配 :与(must) 或(should) 非(must_not)
  • match:分词匹配查询,会对查询条件分词 , multi_match :多字段匹配
  • term:词元查询,不会对查询条件分词
  • range : 查询范围
  • 4.5 文档的映射

ES的文档映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型。

4.5.1 映射字段类型

① 基本字段类型
字符串:text(分词),keyword(不分词) StringField(不分词文本),TextFiled(要分词文本)
text默认为全文文本,keyword默认为非全文文本
数字:long,integer,short,double,float
日期:date
逻辑:boolean
② 复杂数据类型
对象类型:object
数组类型:array
地理位置:geo_point,geo_shape

4.5.2 默认映射

json类型 ==> ES字段类型
Boolean ==> boolean
整数 ==> long
小数 ==> double
日期字符串 ==> date
String ==> string

4.5.3 字段映射的常用属性配置列表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Czn5pksz-1574560932287)(en-resource://database/4157:1)]

4.5.4 添加映射
  • 先添加索引库
put aimall 
  • 再对单个type添加映射
put aimall/goods/_mapping
{
	"goods": {
        "properties": {
            "id": {
                "type": "long"
            },
            "name": {
                "type": "text",
                "analyzer": "ik_smart",
                "search_analyzer": "ik__max__word"
            }
        }
    }
}
  • 或者创建索引库后,直接对多个type进行添加映射
PUT crm
{
  "mappings": {
    "user": {
      "properties": {
        "id": {
          "type": "integer"
        },
        "info": {
          "type": "text",
          "analyzer": "ik_smart",
          "search_analyzer": "ik_smart"
        }
      }
    },
    "dept": {
      "properties": {
        "id": {
          "type": "integer"
        },
        ....其他字段映射配置
      }
    }
  }
}
  • 数组映射:
    数组数据结构
{
	"id" : 1,
	"hobby" : ["football","dabaojian"]
}

文档映射:

{ 
		"properties": {
            "id": {"type": "long"},
            "hobby": {"type": "keyword"}
     }
}
  • 对象映射
    对象数据结构
{
  "id" : 1,
  "girl" : {
      "name" : "扛把子",
      "age"  : 22
  }
}

对象文档映射

{ 
  "properties": {
       "id": {"type": "long"},
       "girl": {
           "properties":{
           		"name": {"type": "keyword"},
           		"age": {"type": "integer"}
           }
        }
  }
}
  • 对象数组映射
    对象数组数据结构
{
	"id" : 1,
	"girl":[{"name":"迪丽热巴","age":23},{"name":"古力娜扎","age":22}]
}

文档映射

"properties": {
        "id": {
            "type": "long"
        },
        "girl": {
            "properties": {
              "age": { "type": "long" },
              "name": { "type": "text" }
            }
        }
}
4.5.5 全局映射

全局映射通过两种方式实现:默认设置和动态模板

  • 默认设置:
    关闭默认的 all ,dept自定义开启 _all
PUT {indexName}
{
 "mappings": {
    "_default_": { 
       "_all": {
        	"enabled": false
       }
  },
  "user": {}, 
  "dept": { 
     "_all": {
      	"enabled": true
     }
  }
 }
  • 动态模板
PUT _template/global_template  //创建名为global_template的模板
{
  "template":   "*",  //匹配所有索引库
  "settings": { "number_of_shards": 1 }, //匹配到的索引库只创建1个主分片
  "mappings": {
    "_default_": {
      "_all": { 
        "enabled": false //关闭所有类型的_all字段
      },
      "dynamic_templates": [
        {
          "string_as_text": { 
            "match_mapping_type": "string",//匹配类型string
            "match":   "*_text", //匹配字段名字以_text结尾
            "mapping": {
              "type": "text",//将类型为string的字段映射为text类型
              "analyzer": "ik_max_word",
              "search_analyzer": "ik_max_word",
              "fields": {
                "raw": {
                  "type":  "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        {
          "string_as_keyword": { 
            "match_mapping_type": "string",//匹配类型string
            "mapping": {
              "type": "keyword"//将类型为string的字段映射为keyword类型
             }
          }
        }
      ]
    }
  }}

映射方式优先级 (低 -> 高):默认 -> 全局 -> 自定义

5 ES集群

5.1 概述

5.1.1 集群优点
  • 避免单节点故障
  • 支持高并发
  • 海量数据存储
5.1.2 ES节点类型

默认情况下,elasticsearch集群中每个节点都有成为主节点的资格,也都存储数据,还可以提供查询服务。在生产环境下,如果不修改elasticsearch节点的角色信息,在高数据量,高并发的场景下集群容易出现脑裂等问题。这些功能是由两个属性控制的。node.master 和 node.data 默认情况下这两个属性的值都是true

配置 类型
node.master=true & node.data=false 主节点
node.master=false & node.data=true 数据节点
node.master=false & node.data=false 负载均衡节点client
  • 主节点 : 代表该节点有成为主资格,主节点的主要职责是和集群操作相关的内容,如创建或删除索引,跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点。一般会把主节点和数据节点分开
  • 数据节点 : 数据节点主要是存储索引数据的节点,主要对文档进行增删改查操作,聚合操作等,数据节点对CPU,IO,内存要求较高,优化节点的时候需要做状态监控,资源不够时要做节点扩充。
  • 负载均衡节点client : 当主节点和数据节点配置都设置为false的时候,该节点只能处理路由请求,处理搜索,分发索引操作等,从本质上来说该客户节点表现为智能负载平衡器。
5.1.3 最佳方案

在一个生产集群中我们可以对这些节点的职责进行划分,建议集群中设置3台以上的节点作为master节点,这些节点只负责成为主节点,维护整个集群的状态。再根据数据量设置一批data节点,这些节点只负责存储数据,后期提供建立索引和查询索引的服务,这样的话如果用户请求比较频繁,这些节点的压力也会比较大,所以在集群中建议再设置一批client节点(node.master: false node.data: false),这些节点只负责处理用户请求,实现请求转发,负载均衡等功能。

5.2 shard及primary/replica shard

  • index包含多个shard,一个shard是最小工作单元,存储部分数据,完整的建立索引和处理索引的能力
  • primary shard不能和自己的replica shard放在同一个节点上 ;
  • 增减节点时,shard会自动在nodes中负载均衡 ;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CXy7QV6N-1574564160423)(en-resource://database/4159:1)]
  • 每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
  • replica shard是primary shard的副本,负责容错,以及承担读请求负载 - 读写分离
  • primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
  • primary shard的默认数量是5,每个主分片上replica默认是1,所以默认有10个shard,5个primary shard,5个replica shard

5.3 不同数量节点的shard分配

5.3.1 单node环境下创建

单node环境下,创建一个index,有3个primary shard,3个replica shard

  • 这个时候,只会将3个primary shard分配到仅有的一个node上去,另外3个replica shard是无法分配的
  • 集群status是yellow
  • 集群可以正常工作,但是一旦出现节点宕机,数据全部丢失,而且此时集群不可用,无法承接任何请求
5.3.2 两个node环境下创建

2个node环境下,创建一个index, 3个primary shard,3个replica shard

  • 每个node下有3个分片,且一组primary shard与replica shard始终不在一个node下
5.3.3 扩容极限,性能更优
  • 每个Node更少的Shard,每个Shard资源跟充沛,性能更高
  • 扩容极限:6个shard(3 primary,3 replica),最多扩容到6台机器,每个shard可以占用单台服务器的所有资源,性能最好
  • 超出扩容极限,动态修改replica数量,9个shard(3primary,6 replica),扩容到9台机器,比3台机器时,拥有3倍的读吞吐量
5.3.4 容错机制
  • master node宕机,自动进行master node选举 状态red
  • Replica容错 : 当某个PrimaryShard (主分片)down机,这个PrimaryShard的下属的某个ReplicShard(备分片)会通过选举成为PrimaryShard,如果新的primaryShard没有replicaShard,此时状态为yellow
  • 如果down机节点恢复重启 , 原内部的PrimaryShard因为已被原来的其他node的ReplicaShard替代位置 , 会变成新的ReplicShard , 如果宕机前有数据,会恢复之前的数据,然后再从新的PrimaryShard中拷贝新的数据 . 这样做的好处是:
    1.恢复性能好
    2.可以避免数据同步延迟造成的数据丢失问题(如在宕机的一瞬间,有些数据还没同步到ReplicShard,可能会导致数据丢失)

5.4 集群搭建

5.4.1 配置说明
- cluster.name

  集群名,自定义集群名,默认为elasticsearch,建议修改,因为低版本多播模式下同一网段下相同集群名会自动加入同一集群,如生产环境这样易造成数据运维紊乱。

- node.name

  节点名,同一集群下要求每个节点的节点名不一致,起到区分节点和辨认节点作用

- node.master

  是否为主节点,选项为truefalse,当为true时在集群启动时该节点为主节点,在宕机或任务挂掉之后会选举新的主节点,恢复后该节点依然为主节点

- node.data

  是否处理数据,选项为truefalse。负责数据的相关操作

- path.data

  默认数据路径,可用逗号分隔多个路径

- path.logs

  默认日志路径

- bootstrap.mlockall

  内存锁,选项为truefalse,用来确保用户在es-jvm中设置的ES_HEAP_SIZE参数内存可以使用一半以上而又不溢出

- network.host

  对外暴露的host,0.0.0.0时暴露给外网

- http.port

  对外访问的端口号,默认为9200,所以外界访问该节点一般为http://ip:9200/

- transport.tcp.port

  集群间通信的端口号,默认为9300

- discovery.zen.ping.unicast.hosts

  集群的ip集合,可指定端口,默认为9300,如 ["192.168.1.101","192.168.1.102"]

- discovery.zen.minimum_master_nodes

  最少的主节点个数,为了防止脑裂,最好设置为(总结点数/2 + 1)- discovery.zen.ping_timeout

  主节点选举超时时间设置

- gateway.recover_after_nodes

  值为n,网关控制在n个节点启动之后才恢复整个集群

- node.max_local_storage_nodes

  值为n,一个系统中最多启用节点个数为n

- action.destructive_requires_name

  选项为truefalse,删除indices是否需要现实名字
5.4.2 修改配置
  • 在每个ES文件/config/elasticsearch.yml中添加以下配置至最后
# 统一的集群名
cluster.name: my-ealsticsearch
# 当前节点名 node-1 node-2 node-3
node.name: node-?
# 对外暴露端口使外网访问
network.host: 127.0.0.1
# 对外暴露端口 9201 9202 9203
http.port: 920?
#集群间通讯端口号 9301 9302 9303
transport.tcp.port: 930?
#集群的ip集合,可指定端口,默认为9300
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

注意:需要准备三个ES(拷贝),然后删除data目录 , 如果电脑内存不够,可以把jvm.properties中的内存设置改小

  • 分别启动三个ES节点 , 访问:http://127.0.0.1:9201/
5.4.3 连接集群
  • 修改kibana配置:./config/kibana.yml
elasticsearch.url: "http://localhost:9201"

连接其中一个节点自然能连接上整个集群 , 然后启动Kibana
查看

GET _cat/nodes?v ==> 查看Node
GET _cat/indices?v ==> 查看索引库

6 Java操作ES集群

6.1 maven方式导入依赖

<dependency>
    <groupId>org.elasticsearch.clientgroupId>
    <artifactId>transportartifactId>
    <version>5.2.2version>
dependency>
<dependency>
    <groupId>org.apache.logging.log4jgroupId>
    <artifactId>log4j-apiartifactId>
    <version>2.7version>
dependency>
<dependency>
    <groupId>org.apache.logging.log4jgroupId>
    <artifactId>log4j-coreartifactId>
    <version>2.7version>
dependency>

6.2 使用工具类连接ES

public class ESClientUtil {

    public static TransportClient getClient(){
        Settings settings = Settings.builder()
        .put("cluster.name","my-ealsticsearch")
        .put("client.transport.sniff", true).build();
        
        TransportClient client = null;
        try {
            client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(
                    		new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return client;
    }
}

6.3 文档的CRUD


/**
 * @Author: Carry
 * @Date: 2019-11-22 18:02
 * @Description:
 */
public class ESClusterTest {
    TransportClient client;
    /**
     * 创建客户端方法
     * */
    @Before
    public void getClient(){
        client = ESClientUtil.getClient();
    }
    /**
     * g关闭客户端
     * */
    @After
    public void close(){
        client.close();
    }

    /**
     * 添加文档
     * */
    @Test
    public void testAdd() throws Exception{
        //创建索引库及类型
        IndexRequestBuilder index = client.prepareIndex("crm", "department", "1");
        //准备数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("id",1);
        map.put("name","科技部");
        map.put("address","chengdu");

        //添加数据并获取返回结果
        IndexResponse response = index.setSource(map).get();
        System.out.println(response);
    }

    /**
     * 获取文档
     * */
    @Test
    public void testGet() throws Exception{
        GetResponse response = client.prepareGet("crm", "department", "6").get();
        //获取文档需要再次调用getSource()方法得到map对象
        Map<String, Object> map = response.getSource();
        System.out.println(map);
    }

    /**
     * 修改文档
     * */
    @Test
    public void testUpdate() throws Exception{
        UpdateRequestBuilder requestBuilder = client.prepareUpdate("crm", "department", "1");
        //准备数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","小卖部");
        map.put("address","成都");
        UpdateResponse response = requestBuilder.setDoc(map).get();

        System.out.println(response);
    }
    /**
     * 删除文档
     * */
    @Test
    public void testDelete() throws Exception{
        DeleteRequestBuilder requestBuilder = client.prepareDelete("crm", "department", "1");
        DeleteResponse response = requestBuilder.get();
        System.out.println(response);
    }

    /**
     * 批量添加
     * */
    @Test
    public void testBulkAdd() throws Exception{
        BulkRequestBuilder requestBuilder = client.prepareBulk();
        //准备数据
        HashMap<String, Object> map1 = new HashMap<>();
        map1.put("id",5);
        map1.put("name","小卖部");
        map1.put("address","成都");
        //准备数据
        HashMap<String, Object> map2 = new HashMap<>();
        map2.put("id",6);
        map2.put("name","公关部");
        map2.put("address","武汉");
        //准备数据
        HashMap<String, Object> map3 = new HashMap<>();
        map3.put("id",7);
        map3.put("name","行政部");
        map3.put("address","杭州");

        BulkResponse responses = requestBuilder
                .add(client.prepareIndex("crm", "department", "5").setSource(map1))
                .add(client.prepareIndex("crm", "department", "6").setSource(map2))
                .add(client.prepareIndex("crm", "department", "7").setSource(map3))
                .get();

        Iterator<BulkItemResponse> iterator = responses.iterator();
        if(iterator.hasNext()){
            System.out.println(iterator.next().getResponse());
            System.out.println(1);
        }
    }

    /**
     * 高级查询带分页
     * */
    @Test
    public void testQueryPage() throws Exception{

        SearchRequestBuilder searchRequestBuilder = client.prepareSearch("crm");
        searchRequestBuilder.setTypes("department");
        searchRequestBuilder.setFrom(0);
        searchRequestBuilder.setSize(10);
        searchRequestBuilder.addSort("id", SortOrder.DESC);

        //查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        List<QueryBuilder> must = boolQueryBuilder.must();
        //DSL查询
        must.add(QueryBuilders.matchQuery("name" , "部"));

        List<QueryBuilder> filter = boolQueryBuilder.filter();
        //DSL过滤
        filter.add(QueryBuilders.rangeQuery("id").lte(6).gte(1));
        filter.add(QueryBuilders.termQuery("address","chengdu"));
        /*此处使用term注意数据的分词器:比如搜索'成都',使用term不会分词,
        但是数据'成都'可能在ES中已经拆分,导致搜索不到*/

        searchRequestBuilder.setQuery(boolQueryBuilder);

        SearchResponse searchResponse = searchRequestBuilder.get();

        SearchHits hits = searchResponse.getHits();

        System.out.println("总条数:"+hits.getTotalHits());
        for (SearchHit hit : hits.getHits()) {
            System.out.println(hit.getSource());

        }
    }
}

你可能感兴趣的:(ElasticSearch+集群配置使用最全详解)