elasticsearch进阶-elasticsearch集群搭建与javaapi与spring整合elasticsearch

倒排索引:根据属性值找到索引(DocID;TF) id是索引,TF是出现几次,通过词查找索引,然后在根据这个拿到的索引去找具体的位置
正派索引:根据索引找到属性值
全文搜索
相关性:
分析:
单词搜索:搜索单个词语
多词搜索:搜索多个词语,可以使用or,and
组合搜索:包含这个条件但是不包含另外一个条件
bool评分的计算规则:
权重:人为的设置词增加权重来影响该条数据的得分->“boost”:10
短语匹配:不仅仅是词要匹配,并且词的顺序也要一致。"slop"可以设置跳过几个字

集群
集群节点
master节点,设置node.master属性为true,就有资格被选为master节点,作用用于控制整个集群的操作,比如创建或删错,管理其他非master节点。
date节点,用于执行数据相关的操作,比如文档的crud
客户端节点,配置文件中node.master和node.date属性均为false,用于响应用户的请求,把请求发送到data节点
部落节点,当一个节点配置了tribe.,他就是一个特殊的客户端,可以连多个集群,在所有连接的集群上执行搜索和其他操作
docker 搭建 elasticsearch集群:
1. /目录下创建es-cluseter/node01、node02
2. 复制安装目录下的jvm.options、 elasticsearch.yml 分别到node01,node02
3. 修改配置文件:
jvm.options 要将1g改成128m(看实际情况)
elasticsearch.yml配置:
discovery.zen.minimum_master_nodes: 1
http.cors.enabled: true
http.cors.allow-origin: "
"
cluster.name: es-cluster
node.name: node01
network.host: 192.168.64.128
http.port: 9300
discovery.zen.ping.unicast.hosts: [“192.168.64.128”]
# 表示这个节点有资格竞选主节点
node.master: true
node.data: true
4. 设置node01,node02访问权限,因为docker启动elasticsearch不是用root用户访问,当把node01和node02和elasticsearch挂载,docker无法向node01或node02里的data文件写数据。 chmod 777 data/ -R
5.进行挂载。docker create --name es-node01 --net host -v /es-cluster/node01/elastisearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /es-cluster/node01/jvm.options:/usr/share/elasticsearch/config/jvm.options -v /es-cluster/node01/data:/usr/share/elasticsearch/data elasticsearch:6.5.4
6.启动并打印日志。 docker start es-node01 && docker logs -f es-node01
head页面的01234表示的是分片,粗框表示的是主分片,细框表示的是副本,

节点宕机(故障转移)
当date节点宕机:集群状态为黄色,表示主节点可用,副本节点不完全可用。过一段时间观察,发现节点列表中没有宕机的节点,副本节点分配到了未宕机的其他节点,集群状态恢复为绿色。
当把date节点恢复后,这个date节点重新加入了集群,并且重新分配了节点信息。
当主节点宕机: 集群装填变为黄色,集群对master进行了重新选举,选举了新的master , ,过一段时间观察,发现节点列表没有了原先宕机的主节点,集群状态恢复为绿色。
当宕机的主节点恢复后,这个节点加不到集群中了。这就是集群中的脑裂问题。
脑裂问题
指挥master变成了多个。
解决方案:不能让节点很容易的变成master,必须有多个节点认可后才可以。 设置minimum_naster_nodes的大小为2(所有节点的都设置),官方推荐(N/2)+1 ,N为集群中节点数。
分布式文档存储路由:在elasitcsearch中,会采用计算的方式来确定存储到哪个节点,计算公式如下:
shard = hash(routing) % number_of_primary_shards
routing值是一个任意字符串,它默认是_id但也可以自定义。
这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0到number_of_primary_shards - 1,这个数字就是特定文档所在的分片。 这就是为什么创建了主分片后不能修改的原因。
写操作: 新建、索引、删除都是写操作,比如对节点三进行写操作,节点三会去请求主节点,在主节点上成功完成了才能复制到相关的复制分片守丧。
搜索文档: 文档能够从主分片或任意一个复制分片进行检索。
全文搜索: 当文档可能分散在各个节点上,那么在分布式的情况下,搜索分为两个阶段,搜索+取回。
客户端发送一个search搜索请求给node3,创建一个长度为from+size的空优先级队列,node3z转发这个搜索到索引中的每个分片的副本或副本,每个分片在本地执行这个查询并将结果返回,一旦所有的文档都返回了,node3将这些值合并到自己的优先队列里并返回给客户端。

java客户端
在Elasticsearch中,为java提供了2种客户端,一种是REST风格的客户端,另一种是Java API的客户端。
REST又分高级客户端和低级客户端。(直接发送POST/GET请求的方式)
低级:


			      org.elasticsearch.client
			      elasticsearch-rest-client
			      6.5.4
			 

与使用RESTful api 几乎一致。
高级:


			  org.elasticsearch.client
			  elasticsearch-rest-high-level-client
			  6.5.4
			

Spring Data 提供了简化 Elasticsearch操作:

            
 		      org.springframework.boot
 		      spring-boot-starter-data-elasticsearch
 		    

编辑properties:

    spring.application.name = itcast-elasticsearch
	spring.data.elasticsearch.cluster-name=es-itcast-cluster
	spring.data.elasticsearch.cluster-
	nodes=172.16.55.185:9300,172.16.55.185:9301,172.16.55.185:9302 
	#这里的9300是api端口,restful端口监听的是9200,api监听的9300

编写User对象:

		@Data
		@AllArgsConstructor
		@NoArgsConstructor
		@Document(indexName = "itcast", type = "user", shards = 6, replicas = 1)
		public class User {
		  @Id
		  private Long id;
		  @Field(store = true)
		  private String name;
		  @Field
		  private Integer age;
		  @Field
		  private String hobby;
		}

		新增数据:
			  @Test

			  public void testSave(){
			    User user = new User();
			    user.setId(1001L);
			    user.setAge(20);
			    user.setName("张三");
			    user.setHobby("足球、篮球、听音乐");
			    IndexQuery indexQuery = new IndexQueryBuilder().withObject(user).build();
			    String index = this.elasticsearchTemplate.index(indexQuery);
			    System.out.println(index);
			 }
		批量插入数据:
			 @Test
			  public void testBulk() {
			    List list = new ArrayList();
			    for (int i = 0; i < 5000; i++) {
			      User user = new User();
			      user.setId(1001L + i);
			      user.setAge(i % 50 + 10);
			      user.setName("张三" + i);
			      user.setHobby("足球、篮球、听音乐");
			      IndexQuery indexQuery = new
				  IndexQueryBuilder().withObject(user).build();
			      list.add(indexQuery);
			   }
			    Long start = System.currentTimeMillis();
			    this.elasticsearchTemplate.bulkIndex(list);
			    System.out.println("用时:" + (System.currentTimeMillis() - start)); 
			 }
		更新数据:
		/**
		  * 局部更新,全部更新使用index覆盖即可
		  */
		  @Test
		  public void testUpdate() {
		    IndexRequest indexRequest = new IndexRequest();
		    indexRequest.source("age", "30");
		    UpdateQuery updateQuery = new UpdateQueryBuilder()
		       .withId("1001")
		       .withClass(User.class)
		       .withIndexRequest(indexRequest).build();
		    this.elasticsearchTemplate.update(updateQuery);
		 }
		删除数据
		@Test
		public void testDelete(){
		  this.elasticsearchTemplate.delete(User.class, "1001");
		}
		搜索
		@Test
		public void testSearch(){
		  PageRequest pageRequest = PageRequest.of(1,10); //设置分页参数
		  SearchQuery searchQuery = new NativeSearchQueryBuilder()
		     .withQuery(QueryBuilders.matchQuery("name", "张三")) // match查询
		     .withPageable(pageRequest)
		     .build();
		  AggregatedPage users =
		this.elasticsearchTemplate.queryForPage(searchQuery, User.class);
		  System.out.println("总页数:" + users.getTotalPages()); //获取总页数
		  for (User user : users.getContent()) { // 获取搜索到的数据
		    System.out.println(user);
		 }
		}

你可能感兴趣的:(elasticsearch,记录)