文章目录
1.引入
1.1 Luence
Lucene是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
1.2 Solr
Solr是一个基于Luence的企业级全文搜索服务器,它童工了比Luence更加丰富的查询语言,同时实现了可配置、可扩展,同时对索引和搜索性能进行了优化。Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中。
Solr 索引的实现方法是用 POST方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引。Solr 搜索只需要使用提供的Web-service的API接口,来发送 HTTP GET 请求,然后对返回XML、json等格式的查询结果进行解析,组织页面布局。
1.3 ElasticSearch
Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
source: 百度百科
2. ElasticSearch安装
2.1 云服务器安装
2.1.1. docker安装
-
搜索镜像:如果
docker search elasticsearch,或者到docker hub中进行搜索
如果不指定版本可能会无法进行安装,因此,最好指定安装的版本号。
-
拉取镜像
docker pull elasticsearch:7.8.0 -
运行镜像并进行端口映射
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/elasticsearch 7.8.0 121454ddad72 6 days ago 810 MB [root@izbp15ffbqqbe97j9dcf5dz ~]# docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -d -p 9200:9200 -p 9300:9300 --name ES01 121454ddad72NOTE:
-e ES_JAVA_OPTS="-Xms512m -Xmx512m":只用指定启动elasticsearch所需的内存大小,elasticsearch默认使用内存大小为2G,,如果不够则无法正常启动。因为我的云服务器只有2G的内存,因此,这里最大可用内存和最小可用内存都为512m-e "discovery.type=single-node":单节点安装要加上,否则会报ERROR: [1] bootstrap checks failed-p 9200:9200 -p 9300:9300:进行端口映射,便于远程访问
-
查看是否正常运行,可以看到正常运行中
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 200c0b2c5735 121454ddad72 "/tini -- /usr/loc..." 11 minutes ago Up 10 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp ES01 afc7a1ab33ce 95bc78c8d15d "docker-entrypoint..." 5 hours ago Up 5 hours 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp rabbitmq 25bd2268623c redis "docker-entrypoint..." 22 hours ago Up 22 hours 0.0.0.0:6379->6379/tcp redis 53b9351e2a7f mysql "docker-entrypoint..." 29 hours ago Up 29 hours 0.0.0.0:3306->3306/tcp, 33060/tcp wizardly_cori [root@izbp15ffbqqbe97j9dcf5dz ~]#
2.1.2 配置安全规则
登录云服务器,选择左侧的安全组中的配置规则,手动添加访问规则:
2.1.3 远程访问
使用ip:9200请求访问elasticsearch,如果浏览器输出如下信息,表示设置成功。
{
"name" : "200c0b2c5735",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "Ef-bRe0lS8Sgg6s7T4y29g",
"version" : {
"number" : "7.8.0",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65",
"build_date" : "2020-06-14T19:35:50.234439Z",
"build_snapshot" : false,
"lucene_version" : "8.5.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
2.2 windows安装
2.2.1 elasticsearch安装
首先到elasticsearch官网下载所需的压缩包
下载结束后解压即可用。找到bin目录下的elasticsearch.bat,双击即可在后台运行elasticsearch服务。接着在浏览器中输入localhost:9200,如果能看到如下信息,说明elasticsearch正常启动
{
"name" : "DESKTOP-5UNDPP9",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "BmT8EaJsRZKDAfj34tmJ2A",
"version" : {
"number" : "7.6.1",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "aa751e09be0a5072e8570670309b1f12348f023b",
"build_date" : "2020-02-29T00:15:25.529771Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
NOTE:
安装elasticsearch确保JDK已正确安装
elasticsearch启动时默认占用内存大小为1G,如果想降低所占内存可到解压目录下的config/jvm.options修改其中的
-Xms和-Xmx参数,如:-Xms512m -Xmx1512m
2.2.2 head插件安装
安装前请确保Nodejs环境已安装~
首先到elasticsearch-head中下载code的压缩包,下载完毕后解压,并到命令行窗口切换到解压目录。运行npm install安装插件,最后使用npm run start命令启动插件。
为了连接前面安装的elasticsearch,还需要解决跨域问题。在elasticsearch的解压目录下找到config/elasticsearch.yml文件,添加如下设置,并使用UTF-8格式保存。不然可能会出现闪退问题:
http.cors.enabled: true
http.cors.allow-origin: "*"
在浏览器中输入localhost:9100访问会看到如下页面,表示启动成功。
在Connect左侧的地址栏中输入http://127.0.0.1:9200/便可连接上elasticsearch。
我使用
http://localhost:9200/无法连接成功,不知道为什么~
2.2.3 安装ElasticHD
elasticsearch-head实在是不符合现代审美,所以可以选择安装ElasticHD,它是一个Elasticsearch 可视化DashBoard, 支持Es监控、实时搜索,Index template快捷替换修改,索引列表信息查看, SQL converts to DSL等。
这里同样只介绍通过云服务器的docker安装,首先到docker hub上搜索镜像
通过docker pull containerize/elastichd命令拉取镜像:
root@izbp15ffbqqbe97j9dcf5dz ~]# docker pull containerize/elastichd
Using default tag: latest
Trying to pull repository docker.io/containerize/elastichd ...
latest: Pulling from docker.io/containerize/elastichd
43d680a959df: Pull complete
de979aec8d7a: Pull complete
1216b09132aa: Pull complete
Digest: sha256:2b20e180418f3b6d0d37f2be4485244960131a9d6ce1d51ab6afbc6f40685e20
Status: Downloaded newer image for docker.io/containerize/elastichd:latest
通过docker ps查看正在运行的elasticsearch服务的名字,我这里是ES01。然后使用docker run -p 9800:9800 -d --link ES01:demo containerize/elastichd命令安装,最后使用docker ps查看是否启动成功。
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker run -p 9800:9800 -d --link ES01:demo containerize/elastichd
427bdf04b78c49794fc65106074476751d58e939bb43a448785354307e855412
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bdf04b78c containerize/elastichd "ElasticHD" 4 seconds ago Up 3 seconds 0.0.0.0:9800->9800/tcp clever_heisenberg
5c09fb35ce4f e2a76963bc18 "/bin/sh -c 'node_..." 4 minutes ago Up 4 minutes 0.0.0.0:9100->9100/tcp ES-Head
200c0b2c5735 121454ddad72 "/tini -- /usr/loc..." 42 hours ago Up 42 hours 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp ES01
afc7a1ab33ce 95bc78c8d15d "docker-entrypoint..." 47 hours ago Up 47 hours 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp rabbitmq
25bd2268623c redis "docker-entrypoint..." 2 days ago Up 2 days 0.0.0.0:6379->6379/tcp redis
53b9351e2a7f mysql "docker-entrypoint..." 2 days ago Up 2 days 0.0.0.0:3306->3306/tcp, 33060/tcp wizardly_cori
此外,为了实现远程访问,还需要在服务器安全组添加安全规则
配置结束后在浏览器输入http://ip:9800/,如果访问成功会看到如下dashboard,并且可以在地址栏中输入http://ip:9200/来连接elasticsearch服务。
2.2.4安装kibana
Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。
首先同样需要elasticsearch官网下载Kibana的压缩包,下载结束后解压即可用。双击运行bin/Kbina.bat即可启动服务,在浏览器中输入localhost:5601可看到如下界面,说明启动成功。
3. Spring Boot整合ElasticSearch
3.1 环境搭建
Spring Boot整合elastissearch首先需要引入其依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
由于Spring Boot自动引入的elasticsearch版本太低,因此,还需要更改elasticsearch的版本,使其和本地安装的版本一致:
<elasticsearch.version>7.8.0</elasticsearch.version>
elasticsearch针对于Java提供了两个版本的客户端来使用它,分别是低版本的RestClient和高版本的RestHighLevelClient,这里演示使用RestHighLevelClient。
最后在Ioc容器中注入RestHighLevelClient,方便后续的使用。
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")
)
);
return client;
}
}
3.2 索引操作
添加索引:
@Test
public void testCreateIndex() throws IOException {
// 创建索引请求
CreateIndexRequest request = new CreateIndexRequest("test.index");
// 客户端执行请求IndicesClient,请求获得响应
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().
create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
// org.elasticsearch.client.indices.CreateIndexResponse@274eb315
}
执行单元测试,查看elasticsearch发现test.index已经添加成功。
查询索引是否存在:
@Test
public void testIndexExist() throws IOException {
GetIndexRequest request = new GetIndexRequest("test.index");
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists); // true
}
执行单元测试,控制台输出true,表示之前添加的test.index确实存在。
删除索引
@Test
public void testIndexDelete() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("test.index");
AcknowledgedResponse delete = restHighLevelClient.indices().delete(request,
RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged()); // true
}
执行单元测试,查看elasticsearch发现test.index已经被删除。
3.3 文档操作
添加文档
@Test
public void testAddDoc() throws IOException {
Person person = Person.builder().name("kobe").age(18).build();
// 创建请求
IndexRequest request = new IndexRequest("test.index");
request.id("1");
request.timeout(TimeValue.timeValueMinutes(1));
request.timeout("1s");
// 将数据放入请求
request.source(JSON.toJSONString(person), XContentType.JSON);
// 客户端发送请求 , 获取响应的结果
IndexResponse indexResponse = restHighLevelClient.index(request,
RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
System.out.println(indexResponse.status());
}
执行单元测试,控制台输出:
IndexResponse[index=test.index,type=_doc,id=1,version=2,result=updated,seqNo=1,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
OK
同时查看elasticsearch,发现确实添加成功。
判断文档是否存在
@Test
public void testFetDoc() throws IOException {
GetRequest getRequest = new GetRequest("test.index", "1");
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists); // true
}
执行单元测试,控制台输出true,表示之前添加的索引是存在的。
获取文档信息:
void testGetDocInfo() throws IOException {
GetRequest getRequest = new GetRequest("test.index", "1");
GetResponse getResponse = restHighLevelClient.get(getRequest,
RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());
System.out.println(getResponse);
}
执行单元测试,控制台输出:
{"age":18,"name":"kobe"}
{"_index":"test.index","_type":"_doc","_id":"1","_version":2,"_seq_no":1,
"_primary_term":1,"found":true,"_source":{"age":18,"name":"kobe"}}
更新文档:
@Test
void testUpdateRequest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("test.index","1");
updateRequest.timeout("1s");
Person person = Person.builder().name("James").age(34).build();
updateRequest.doc(JSON.toJSONString(person),XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest,
RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
执行单元测试,观察elasticsearch中文档的情况,发现更新成功。
删除文档
@Test
void testDeleteRequest() throws IOException {
DeleteRequest request = new DeleteRequest("test.index","1");
request.timeout("1s");
DeleteResponse deleteResponse = restHighLevelClient.delete(request,
RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
执行单元测试后,观察elasticsearch中索引的情况,发现此时test.index已经不在了,删除操作执行成功。
3.4 批量操作
3.4.1 批量添加
@Test
public void testBulkRequest() throws IOException{
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("1s");
List<Person> list = new ArrayList<>();
Collections.addAll(list, new Person("Kobe", 18),
new Person("James", 34),
new Person("Ball", 24));
for (int i = 0; i < list.size(); i++) {
bulkRequest.add(new IndexRequest("test.index").id(" " + i + 1)
.source(JSON.toJSONString(list.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures());
}
执行单元测试,查看elasticsearch可以看到所有的文档均添加到了test.index中。
3.4.2 批量查询
@Test
void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("test.index");
// 构建搜索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.highlighter();
// 查询条件,我们可以使用 QueryBuilders 工具来实现
// QueryBuilders.termQuery 精确
// QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", "18");
// // MatchAllQueryBuilder matchAllQueryBuilder =
// QueryBuilders.matchAllQuery();
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest,
RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
System.out.println("=================================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
执行单元测试,控制台输出
{"fragment":true,"hits":[{"fields":{},"fragment":false,"highlightFields":{},
"id":" 01","matchedQueries":[],"primaryTerm":0,"rawSortValues":[],
"score":1.0,"seqNo":-2,"sortValues":[],"sourceAsMap":{"name":"Kobe","age":18},
"sourceAsString":"{\"age\":18,\"name\":\"Kobe\"}",
"sourceRef":{"fragment":true},"type":"_doc","version":-1}],
"maxScore":1.0,"totalHits":{"relation":"EQUAL_TO","value":1}}
=================================
{name=Kobe, age=18}