一、导包

二、核对导入的ES版本

我的springboot自动导入的是7.6.2的版本,但我搭建的ES是7.7.0,为了避免出异常,需修改导入版本与ES服务版本一致

修改导入版本

  1. 查看springboot版本号使用的什么properties标签

    • 打开pom文件->按住ctrl点击artifactId

    • 在弹出的pom中按住Ctrl点击artifactId

    • 在弹出的pom中找到elasticsearch版本标签

    • 在项目的pom文件properties标签中添加需要导入的版本

    • 这时回到刚才第一张图,看es就会变成了指定的版本了

三、写配置类

我是用的是RestHighLevelClient ,通过官方文档得知,它需要返回一个RestHighLevelClient 对象,并且使用完后及时关闭客户端

  • 我的配置类

    package com.rb.elasticsearch.elasticsearch.conf;
    
    import org.apache.http.HttpHost;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration; @Configuration
    public class EsConf {
    @Bean
    public RestHighLevelClient restHighLevelClient(){
    RestHighLevelClient client = new RestHighLevelClient(
    RestClient.builder(
    //new HttpHost("localhost", 9200, "http"),//如果集群,传入多个地址即可
    new HttpHost("192.168.100.112", 9200, "http")));//我的ES地址端口
    return client;
    }
    }
    //可以自己写一个自动装配类,将ip写入Yml文件

四、开始测试

索引操作

1.创建索引

注意:索引名字必须小写

返回值为:{"acknowledged":true,"fragment":false,"shardsAcknowledged":true}

这个返回值和elasticsearch-head创建索引返回的结果一样

代码如下:

package com.rb.elasticsearch.elasticsearch;

import com.alibaba.fastjson.JSON;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import java.io.IOException; @SpringBootTest
class ElasticsearchApplicationTests {
@Autowired
RestHighLevelClient restHighLevelClient; /**
* 创建索引
* @throws IOException
*/
@Test
void createIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("java_index");
CreateIndexResponse createIndexResponse =restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(createIndexResponse));//返回值
} }

2.查看索引是否存在

    /**
* 判断索引是否存在
* @throws IOException
*/
@Test
void checkIndex() throws IOException {
GetIndexRequest getIndexRequest=new GetIndexRequest("java_index");
boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);//返回值true:存在 false:不存在
}

3.删除索引

acknowledged=true表示删除成功

    /**
* 判断索引是否存在
* @throws IOException
*/
@Test
void delIndex() throws IOException {
DeleteIndexRequest deleteIndexRequest=new DeleteIndexRequest("java_index");
AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(delete));//返回值{"acknowledged":true,"fragment":false}
}

文档操作

官方举例是手拼json串,但工作中很少这么用,大多数都是一个model,然后转成json串,所以先创建一个model

package com.rb.elasticsearch.model;

import lombok.Data;

@Data
public class Users {
String name;
String remark;
int age;
}

1.添加文档

  • 单条添加

    /**
    * 添加文档
    */
    @Test
    void putDoc() throws IOException {
    if(checkIndexIsExist()){//这个方法见下方“查看文档是否存在” 如果不判断是否存在,在没有创建索引的情况下,它会创建索引
    IndexRequest indexRequest=new IndexRequest(Es.INDEX_NAME);
    indexRequest.id("1");
    Users users=new Users();
    users.setAge(15);
    users.setName("张三的名字叫张三");
    users.setRemark("张三的备注");
    indexRequest.source(JSON.toJSONString(users), XContentType.JSON);
    IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    System.out.println(JSON.toJSONString(index));
    }else{
    System.out.println("索引不存在");
    }
    }
  • 批量添加

     /**
    * 批量添加
    * @throws IOException
    */
    @Test
    void bulkAddDoc() throws IOException {
    if(checkIndexIsExist()){//如果不判断是否存在,在没有创建索引的情况下,它会创建索引
    BulkRequest request=new BulkRequest();
    for (int i = 0; i <5 ; i++) {//循环添加五个
    int id = i+1;
    IndexRequest indexRequest=new IndexRequest(Es.INDEX_NAME);
    Users users=new Users();
    users.setRemark("李"+i+"的备注");
    users.setName("李"+i+"的名字叫李"+i);
    users.setAge(i);
    indexRequest.source(JSON.toJSONString(users),XContentType.JSON);
    indexRequest.id(String.valueOf(id));
    request.add(indexRequest);
    }
    BulkResponse bulk = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
    System.out.println(JSON.toJSONString(bulk));
    }
    }

2.查看文档是否存在

    /**
* 查看文档是否存在
* @throws IOException
*/
@Test
void checkDocIsExist() throws IOException {
if(checkIndexIsExist()){
GetRequest getRequest=new GetRequest(Es.INDEX_NAME,"1");
boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);//true 存在 false 不存在
}else{
System.out.println("索引不存在");
}
}

3.修改文档

注意:我的users对象中age是int,默认值是0,如果执行下面批量修改的时候,age不修改的话会默认是0,这样会将相关索引中age字段值全部修改为0,可以使用Integer

  • 单一修改
 /**
* 单一修改数据
* @throws IOException
*/
@Test
void updateDoc() throws IOException {
if(checkIndexIsExist()){
UpdateRequest updateRequest=new UpdateRequest(Es.INDEX_NAME,"1");
Users users=new Users();
users.setAge(99);//只修改年龄,其他不动
updateRequest.doc(JSON.toJSONString(users),XContentType.JSON);
restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
}
}
  • 批量修改

    /**
    * 批量修改数据
    * @throws IOException
    */
    @Test
    void buleUpdateDoc() throws IOException {
    if(checkIndexIsExist()){
    BulkRequest bulkRequest=new BulkRequest();
    for (int i = 0; i <5 ; i++) {
    int id =i+1;
    UpdateRequest updateRequest=new UpdateRequest(Es.INDEX_NAME,String.valueOf(id));
    Users users=new Users();
    users.setRemark("批量修改的备注"+i);
    updateRequest.doc(JSON.toJSONString(users),XContentType.JSON);
    bulkRequest.add(updateRequest);
    }
    restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
    }
    }

4.删除文档

  • 单独删除
    /**
* 删除文档
* @throws IOException
*/
@Test
void delDoc() throws IOException {
if(checkIndexIsExist()){//只有索引已经创建的时候才可以继续
DeleteRequest deleteRequest=new DeleteRequest("java_index","1");
DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(delete);
}
}
  • 批量删除
/**
* 批量删除
* @throws IOException
*/
@Test
void buleDelDoc() throws IOException {
if(checkIndexIsExist()){
BulkRequest bulkRequest=new BulkRequest();
for (int i = 0; i <5 ; i++) {
int id =i+1;
DeleteRequest deleteRequest=new DeleteRequest(Es.INDEX_NAME);
deleteRequest.id(String.valueOf(id));
bulkRequest.add(deleteRequest);
}
restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
}
}

五.文档常用查询

单一字段查询

根据id精准查询

 /**
* 根据id查询
* @throws IOException
*/
@Test
void termSelectById() throws IOException {
if(checkIndexIsExist()){
GetRequest getRequest1 = new GetRequest(Es.INDEX_NAME, "1");
//也可使用下面的方式
//GetRequest getRequest=new GetRequest(Es.INDEX_NAME);
//getRequest.id("1");
GetResponse documentFields = restHighLevelClient.get(getRequest1, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(documentFields));
}
}

根据某字段精准查询

(select * from users where age=1)

  /**
* 根据某字段精准查询
* @throws IOException
*/
@Test
void termSelectByField() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest=new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("age",1));
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search));
}
}

根据某字段模糊查询

(select * from users where remark like '%0%')

/**
* 根据某个字段模糊查询
* @throws IOException
*/
@Test
void matchSelectByField() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest=new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("remark","0"));
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits().getHits()));
}
}

多条件查询

多条件And查询

(select * from users where name like '%因为是match,会被分词%' and age=0)

    /**
* 多条件查询
* @throws IOException
*/
@Test
void multipleFieldSelectByMust() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest = new SearchRequest(Es.INDEX_NAME);//定义请求
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//构建查询条件器
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//选择返回值(满足查询条件的返回true,不满足是false)
boolQueryBuilder.must(QueryBuilders.matchQuery("name","李0的名字叫李0"));//查询条件一
boolQueryBuilder.must(QueryBuilders.termQuery("age","0"));//查询条件二
System.out.println(boolQueryBuilder.must());//输出构建好的查询条件一、二
searchSourceBuilder.query(boolQueryBuilder);//将条件完善的对象放入
searchRequest.source(searchSourceBuilder);//向查询请求中放入查询条件
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//执行查询
System.out.println(JSON.toJSONString(search.getHits().getHits()));//查看结果
}
}

这一步我认为有点绕,java代码逻辑和上一篇说的命令先后逻辑是一样的,我的研究方式为逆推法(自己这么起的名字)

  • 第一步:restHighLevelClient.search先把这个敲出来,发现这个方法需要一个SearchRequest对象

  • 第二步:new 一个 SearchRequest 这个对象,然后命令顺序下一步是“query”,我就找到了searchSourceBuilder.query()方法,重复第一步,发现query方法需要一个BoolQueryBuilder对象

  • 第三步:new 一个 BoolQueryBuilder这个对象,然后重复第二步,观察命令顺序,这时会传入must\must_not等信息,我就在官方提供的QueryBuilders中找到了相应的方法boolQueryBuilder.must()

    • 这时,我发现一个卡点,命令上会传入一个多条件数组,java中肯定会传入一个多条件的对象,但是没有在QueryBuilders找到入参为数组的, 愁坏我了,去官网翻了一下,看到了下图,意思是可多调用多次,然后我就调用了两次
  • 第四步:因为第三步不确定,但是BoolQueryBuilder这个类中却有返回一个数组的方法,调用看看

    System.out.println(boolQueryBuilder.must());//输出构建好的查询条件一、二
  • 结果和我想的一样,成功了

  • 为了加深上面的印象,我将这块命令顺序同步标记了一下java代码的位置,更方便理解:

GET users/_doc/_search //后的_search就是 SearchRequest 定义请求
{
"query":{//searchSourceBuilder.query(boolQueryBuilder);//将条件完善的对象放入
"bool":{//BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//选择返回值(满足查询条件的返回true,不满足是false)
"must":[//boolQueryBuilder.must()
{
"term"://QueryBuilders.termQuery("age","0");每调用一次就多一个查询条件
{
"name":"张三的名字叫张三"
}
} ,
{
"match"://QueryBuilders.matchQuery("name","李0的名字叫李0")
{
"age":"15"
}
}
]
}
}
}

多条件OR查询

(select * from users where remark like '%1%' or age=0) 注:%1%里的1使用了match,会被分词

/**
* 多条件查询OR
* @throws IOException
*/
@Test
void multipleFieldSelectByShould() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest = new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.should(QueryBuilders.matchQuery("remark","1"));
boolQueryBuilder.should(QueryBuilders.termQuery("age","0"));
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits().getHits()));
}
}

多条件!=查询

(select * from users where age !=0 and age !=1)

/**
* 多条件查询!=
* @throws IOException
*/
@Test
void multipleFieldSelectByMustNot() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest = new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.mustNot(QueryBuilders.termQuery("age","1"));//QueryBuilders里面的查询方式可以随意换
boolQueryBuilder.mustNot(QueryBuilders.termQuery("age","0"));//QueryBuilders里面的查询方式可以随意换
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits().getHits()));
}
}

范围查询

(select * from users where age >=0 and age <=2)

gt 大于

gte 大于等于

lt 小于

lte 小于等于!

 /**
* 根据字段范围查询
* @throws IOException
*/
@Test
void multipleFieldSelectByRange() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest = new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//再此处还可以加上面的各种查询条件↓↓↓
//再此处还可以加上面的各种查询条件↑↑↑
boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(0));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").lte(2));
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits().getHits()));
}
}

自定义字段返回

    /**
* 显示指定字段
* @throws IOException
*/
@Test
void returnField() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest = new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
String[] includeFields = new String[] {"name", "age"};//要显示的哪些字段
String[] excludeFields = new String[] {""};//要排除的哪些字段
searchSourceBuilder.fetchSource(includeFields,excludeFields);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits().getHits()));
}
}

排序

select * from users where remark like '%的备注%' and remark like '%3%' order by _score desc , age desc

查询包含“的备注”、“3”的记录(传入参数会被分词),并且按照匹配度_score这个字段排序,数值越大的匹配度越高,然后按照年龄age降序排序

/**
* 排序
* @throws IOException
*/
@Test
void sort() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest = new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("remark","的备注 3"));
searchSourceBuilder.sort("_score",SortOrder.DESC);
searchSourceBuilder.sort("age",SortOrder.DESC);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search));
}
}

高亮查询

public String test() throws IOException {
SearchRequest searchRequest=new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
//构建查询条件start
searchSourceBuilder.query(QueryBuilders.matchQuery("name","名 叫"));//模糊搜索
//searchSourceBuilder.query(QueryBuilders.termQuery("name.keyword","李0的名字叫李0"));//精准搜索
//构建查询条件end
//高亮start
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
//highlightBuilder.field("name.keyword");//与上方设置的name保持一致
highlightBuilder.preTags("<mytag style='color:red'>");//自定义标签&样式
highlightBuilder.postTags("</mytag>");//自定义标签&样式
searchSourceBuilder.highlighter(highlightBuilder);
//高亮end
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
List<Map<String, Object>> list=new ArrayList();
//高亮条件封装start
for (SearchHit hit : search.getHits().getHits()) {
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField remark = highlightFields.get("name");
// HighlightField remark = highlightFields.get("name.keyword");//与上方设置的name保持一致
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
if(remark!=null){
Text[] fragments = remark.fragments();
String desc="";
for (Text fragment : fragments) {
desc+=fragment;
}
//sourceAsMap.put("name.keyword",desc);
sourceAsMap.put("name",desc);
list.add(sourceAsMap);
}
}
//高亮条件封装end
return JSON.toJSONString(search);
}

结果如下:

获得指定索引下满足条件的总记录数据

    /**
* 查询指定索引中总共有多少条数据
* @throws IOException
*/
@Test
void getTotalCount() throws IOException {
CountRequest countRequest = new CountRequest(Es.INDEX_NAME);
//可以自定义设置上面的一些查询条件start
//可以自定义设置上面的一些查询条件end
CountResponse count = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(count));
}

分页查询

from:从第几条数据开始(>关系,非>=)

size:查询几条数据

/**
* 分页查询
* @throws IOException
*/
@Test
void pageSelect() throws IOException {
if(checkIndexIsExist()){
SearchRequest searchRequest=new SearchRequest(Es.INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置搜索条件
searchSourceBuilder.query(QueryBuilders.matchQuery("remark","的备注"));
searchSourceBuilder.from(2);//从索引第几个开始查找,索引从0 开始
searchSourceBuilder.size(2);//显示from至from+size的数据
//例如:查询id1~2的数据,from=0 ,size=2
// 查询id3-4的数据,from=2, size=2
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits().getHits()));
}
}

六、集成好的项目

https://files-cdn.cnblogs.com/files/rb2010/elasticsearch.zip

ElasticSearch集成SpringBoot与常见使用方法的更多相关文章

  1. 京东云开发者|ElasticSearch降本增效常见的方法

    Elasticsearch在db_ranking 的排名又(双叒叕)上升了一位,如图1-1所示;由此可见es在存储领域已经蔚然成风且占有非常重要的地位. 随着Elasticsearch越来越受欢迎,企 ...

  2. elasticsearch 集成springboot

    和jpa类似,很简单,很强大. pom <dependencies> <dependency> <groupId>org.springframework.boot& ...

  3. Oracle之常见问题诊断方法

    Oracle认证:常见问题诊断方法如下: 1.TNS-12154 Error 或ORA-12154 特征:SQL*NET没有找到连接串或别名 原因1:(1)没有找到TNSNAMES.ORA文件,该文件 ...

  4. 100m和1000m网线的常见制作方法

    100m和1000m网线的常见制作方法 100m和1000m网线的常见制作方法: 5类线(100m)的制作: a: 绿白(3).绿(6).橙白(1).蓝(4).蓝白(5).橙(2).棕白(7).棕(8 ...

  5. OpenStack安装部署管理中常见问题解决方法

    一.网络问题-network 更多网络原理机制可以参考<OpenStack云平台的网络模式及其工作机制>. 1.1.控制节点与网络控制器区别 OpenStack平台中有两种类型的物理节点, ...

  6. Web Deploy发布网站及常见问题解决方法(图文)

    Web Deploy发布网站及常见问题解决方法(图文) Windows2008R2+IIs7.5 +Web Deploy 3.5 Web Deploy 3.5下载安装 http://www.iis.n ...

  7. Quartz总结(一):Quartz集成Spring的2个方法

    零.引言 关于Spring集成Quartz有2种方法: 1. JobDetailBean. 2. MethodInvokeJobDetailFactoryBean. 以下从自身使用和理解以及掌握的知识 ...

  8. Python_socket常见的方法、网络编程的安全注意事项、socketsever模块、浏览器中在一段时间记录用户的登录验证机制

    1.socket常见的方法 socket_常见方法_服务器端 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket. ...

  9. 【异常处理】Springboot对Controller层方法进行统一异常处理

    Controller层方法,进行统一异常处理 提供两种不同的方案,如下: 方案1:使用 @@ControllerAdvice (或@RestControllerAdvice), @ExceptionH ...

随机推荐

  1. CKKS Part2: CKKS的编码和解码

    该文章翻译自CKKS EXPLAINED, PART 2: FULL ENCODING AND DECODING,主要介绍CKKS方案中是如何编码和解码的(如何将复数向量转成整数多项式,以及如何求逆运 ...

  2. Web:移动端阻止默认行为的小坑

    问题 移动端 web 开发中,使用 addEventListener 阻止了 touchstart 事件的默认行为却发现没有生效 描述 再移动端 web 开发中,我们一般会用 addEventList ...

  3. mac不能用ip访问项目的, 还有80端口不能开启的问题

    开启80端口 参考这篇文章 解决mac无法使用80端口问题,亲测可用 1. 防火墙设置问题 2. 网卡问题 3. 服务器地址配置问题

  4. 【HDU6662】Acesrc and Travel(树型Dp)

    题目链接 大意 给出一颗树,每个点上有一个权值\(A[i]\),有两个绝顶聪明的人甲和乙. 甲乙两人一起在树上轮流走,不能走之前经过的点.(甲乙时刻在一起) 甲先手,并可以确定起点.甲想要走过的点权之 ...

  5. 2018 PHP面试题

    2018 PHP面试题 题目来自<PHP程序员面试笔试宝典>,里面涵盖了近三年了各大型企业常考的PHP面试题,针对面试题提取出来各种面试知识也涵盖在了本书. 1.PHP常考基础 1.PHP ...

  6. Solution -「LOJ #6053」简单的函数

    \(\mathcal{Description}\)   Link.   积性函数 \(f\) 满足 \(f(p^c)=p\oplus c~(p\in\mathbb P,c\in\mathbb N_+) ...

  7. CentOS 7.6 部署 GlusterFS 分布式存储系统

    文章目录 GlusterFS简介 环境介绍 开始GlusterFS部署 配置hosts解析 配置GlusterFS 创建文件系统 安装GlusterFS 启动GlusterFS 将节点加入到主机池 创 ...

  8. Linux 下 Git版本升级

    一.下载需要安装的版本号 wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.24.0.tar.gz 二.安装需求 yum ...

  9. Redis原理再学习04:数据结构-哈希表hash表(dict字典)

    哈希函数简介 哈希函数(hash function),又叫散列函数,哈希算法.散列函数把数据"压缩"成摘要,有的也叫"指纹",它使数据量变小且数据格式大小也固定 ...

  10. [旧][Android] View 工作原理(二)

    备注 原发表于2016.05.27,资料已过时,仅作备份,谨慎参考 前言 本文大量参照<Android 开发艺术探索>及参考资料的内容整合,主要帮助自己理清 View 的工作原理.深入学习 ...