赞
踩
文章整理自:狂神说-es
1.Lucence
是一套信息检索工具包,jar包!不包含搜索引擎系统
包含:索引结构、读写索引的工具、排序、搜索规则等工具类
2.Lucence与ElasticSearch关系
ElasticSearch是基于Lucence做了一些封装和增加(上手简单)
3.ElasticSearch与solr的区别
性能对比:以下5图进行了对比
ElasticSearch VS solr 总结
1.es基本是开箱即用(解压就可以使用),非常简单。solr安装略微复杂
2.solr利用zookeeper进行分布式管理,而es自身带有分布式协调管理功能
3.solr支持更多数据格式,如JSON、XML、CSV,而es仅支持json文件格式(少而精)。
4.solr官方提供的功能更多,而es本身更注重于核心功能,高级功能多有第三方插件提供(如ik分词器,图形化界面需要kinaba支持)
5.solr查询快,但更新索引时慢(即插入/删除慢),用于电商等查询多的应用;
环境要求:jdk 1.8及以上、es客户端、界面工具
java开发,es的版本和jdk版本要对应
es与kinaba下载版本要一致
# 创建目录
#es
mkdir -p /opt/apps/es/elasticsearch/{config,data,plugins}
# kibana
mkdir -p /opt/apps/es/kibana/config
es配置文件:
vi /opt/apps/es/elasticsearch/config/elasticsearch.yml
http.port: 9200
http.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"
kibana配置文件
vi/opt/apps/es/kibana/config/kibana.yml
server.name: kibana
# kibana的主机地址 0.0.0.0可表示监听所有IP
server.host: "0.0.0.0"
# kibana访问es的URL
elasticsearch.hosts: [ "http://localhost:9200" ]
#elasticsearch.username: 'kibana'
#elasticsearch.password: '123456'
# 显示登陆页面
#xpack.monitoring.ui.container.elasticsearch.enabled: true
# 语言
i18n.locale: "zh-CN"
vi /opt/apps/es/docker-compose.yml
version: '3' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.9.3 container_name: elasticsearch environment: - "discovery.type=single-node" - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" volumes: - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml - ./elasticsearch/data:/usr/share/elasticsearch/data - ./elasticsearch/plugins:/usr/share/elasticsearch/plugins ulimits: memlock: soft: -1 hard: -1 ports: - 9200:9200 - 9300:9300 restart: always network_mode: 'host' kibana: image: docker.elastic.co/kibana/kibana:7.9.3 volumes: - ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml environment: - ELASTICSEARCH_URL=http://localhost:9200 ports: - 5601:5601 restart: always network_mode: 'host' es-head: image: tobias74/elasticsearch-head:6 container_name: es-head restart: always ports: - "9100:9100"
chmod -R 777 /opt/apps/es/elasticsearch/data
cd /opt/apps/es
docker-compose up -d
firewall-cmd --add-port=9200/tcp --permanent
firewall-cmd --add-port=5601/tcp --permanent
firewall-cmd --reload
es访问地址:
http://ip:9200/
http://192.168.229.132:9200/
kibana访问地址:
http://ip:5601/
http://192.168.229.132:5601/
es-head访问地址:
http://192.168.229.132:9100/
# 进到es plugins的目录 cd /opt/apps/es/elasticsearch/plugins/ # 创建ik 目录 mkdir ik # 进到ik cd /opt/apps/es/elasticsearch/plugins/ik # 下载方式1:分词器,很慢; wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.9.3/elasticsearch-analysis-ik-7.9.3.zip #下载方式2:可以windows直接下载zip包后上传到linux。 # 在谷歌浏览器输入 #https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.9.3/elasticsearch-analysis-ik-7.9.3.zip # 解压分词器 unzip elasticsearch-analysis-ik-7.9.3.zip #重启es docker restart 容器id
集群、节点、索引、类型、文档、分片、映射是什么
es是面向文档,关系型数据库和es概念对比
es集群中可包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)
**物理设计 **:
es在后台把每个索引划分成多个分片,每份分片可以在集群中不同的服务器进行迁移
** 逻辑设计**:
es是面向文档的,意味着索引和搜索数据的最小单位是文档,es中文档有几个重要属性
尽管可以随意的新增或忽略某个子弹,但是每个字段的类型非常重要,比如年龄字段类型,可以是字符或整形。
因为es会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在es中,类型有时候也称为映射类型
物理设计:
一个集群至少一个节点,而一个节点就是一个es进程,默认的节点可以有多个索引,如果创建索引,索引将会由5个分片构成(主分片),每个主分片会有一个副本(复制分片)
如下创建了1个索引:P,副本R,分片结果如下:
上图是一个有3个节点的es集群,可以看到主分片和对应的复制分片都不会再同一个节点内,这样就利于某个节点挂了,数据也不至于丢失。实际上,一个分片就是一个lucence索引,一个包含倒排索引的文件目录,倒排索引的结构使得es在不扫描全部文档的情况下,就能知道哪些文档包含特定的关键字。
倒排索引,优化效率
es使用的一种称为倒排索引的结构,采用lucence倒排索引作为底层。这种结构试用与快速的全文搜索,一个索引由文档中所有不重复的列构成,对于每一个词,都有一个包含他的文档列表。例如现有两个文档,内容如下
sduty every day , good good up to forever # 文档1包含的内容
To forever ,study every day ,good good up # 文档2包含的内容
为了创建倒排索引,我们首先要将每个文档拆分成独立的词语(或称为词条或tokens),然后创建一个包含所有不重复的词条的排列,单号列出每个词条再哪个文档:
现在试图搜索to forever,需要查看包含每个词条的文档,如下:
具体例子:
如现在要搜索linux,那么就根本不会去查询id为1和2的文档,效率非常高
分词:即把一段中文或别的划分成一个个关键字,在搜索时候会把自己的信息进行分词,会把数据库中或索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是每个字分为一个词;
比如“小鸡爱吃大米”会分成“小、鸡、爱、吃、大、米”,这显然无法达到分词要求,所以需要安装中文分词起ik分词器来解决
IK提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度切分
1.ik分词器下载
2.下载后放到es插件包即可
3.解压就可以使用
4.重启es相关服务
kibana上进行操作,测试ik分词器
现象:如“别搞了”,希望分词时出现“别搞了”
处理方式:
当前目录ik分词器配置目录如下:
/opt/apps/es/elasticsearch/plugins/ik/config
增加词典:bie.dic
vi bie.dic
别搞了
#保存
配置文件名:IKAnalyzer.cfg.xml
一种软件架构风格,而不是标准,只是提供了一组设计原则和约束原则。它主要用于客户端和服务器交互类的软件。基于这个风格设计软件可以更加简洁,更有层次,更易于实现缓存等机制。
put
创建索引
PUT /索引名/类型名/文档id #未来类型名会被去掉
{请求提}
kibana索引管理:http://192.168.229.132:5601/app/management/data/index_management/indices
es-head查看索引
设定数据类型
为testbie2索引的字段指定数据类型
获取规则
GET testbie2
GET命令查看es索引情况
PUT修改,body里面的类容就是最终值(更新所有)
修改之前testbie/test/1的值,version代表修改版本变化次数
GET验证修改是否成功:
post
更新/新增
_update后缀,只更新出现的属性
没有_update后缀,依然是更新所有的属性
DELETE删除
删除索引,后缀精确到索引;删除文档行,后缀精确到文档行
GET
GET testbie/test/_search?q=name:别
select (排序、分页、高亮、模糊查询、精准查询)
查询匹的配度:_score(权重)
GET /索引/类型/_search
{
#具体查询条件
}
如下图:
其中hits对应java中的Hits对象,包含以下内容
hit:
1.索引和文档信息
2.查询的结果总数
3.查询出来的具体文档信息
4.查询的数据都可以遍历出来
5.分数越大匹配度越大
_source与query平级
sort,与query平级
sort排升序:
一定要有这两个参数,相当于mysql的limit两个参数
from:0 #从哪里开始
sizi: 10 #取多少条值
多条件bool值查询,
must匹配相当于mysql的and操作,所有条件都要符合
must_not 匹配相当于mysql的 != 操作
should 匹配相当于mysql的or操作
filter与must平级
gt大于,lt小于,gte大于等于,lte小于等于
match自带模糊查询,多个条件用空格隔开
term:精确查询
match:模糊查询
term与match平级
两个类型,在设定字段类型时要注意
text:会被分词器解析成多个词
keyworkd:不会被分词器解析
highlight与query平级,高亮的字段都会用"em"标签包裹返回
自定义高亮标签:
es官网 https://www.elastic.co/guide/index.html#viewall
es客户端:
使用java rest客户端
es使用java rest客户端对应官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/index.html
依赖版本需要和es服务端版本一致
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.9.3</version>
</dependency>
略
版本不匹配
核心类:RestClietConfigartions
package com.bie.config; 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; /** * @author bjh * @date 2022/12/9 */ @Configuration public class ElasticSearchClientConfig { @Bean public RestHighLevelClient restHighLevelClient() { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("192.168.229.132", 9200, "http"))); return client; } }
package com.bie; 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.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException; /** * es 7.9.3客户端api测试 */ @RunWith(SpringRunner.class) @SpringBootTest public class JavaEsApiApplicationTests { @Autowired @Qualifier("restHighLevelClient") private RestHighLevelClient client; /** * 创建索引 * Request */ @Test public void createIndex() throws IOException { // 1.创建索引请求 CreateIndexRequest bieIndex = new CreateIndexRequest("bie_index"); // 2.执行索引请求 CreateIndexResponse createIndexResponse = this.client.indices().create(bieIndex, RequestOptions.DEFAULT); System.out.println(createIndexResponse.toString()); } }
/**
* 获取索引
* @throws IOException
*/
@Test
public void getIndex() throws IOException {
// 1.创建获取索引请求
GetIndexRequest bieIndex = new GetIndexRequest("bie_index");
// 2.执行索引请求
boolean exists = this.client.indices().exists(bieIndex, RequestOptions.DEFAULT);
System.out.println(exists);
}
/**
* 删除索引
*
* @throws IOException
*/
@Test
public void deleteIndex() throws IOException {
// 1.创建获取索引请求
DeleteIndexRequest bieIndex = new DeleteIndexRequest("bie_index");
// 2.执行索引请求
boolean isDeleteSuccess = this.client.indices().delete(bieIndex, RequestOptions.DEFAULT).isAcknowledged();
System.out.println(isDeleteSuccess);
}
/** * 添加文档 * * @throws IOException */ @Test public void addDoc() throws IOException { // 1.创建 索引请求对象 IndexRequest indexRequest = new IndexRequest("bie_index"); indexRequest.timeout(TimeValue.timeValueSeconds(1)); indexRequest.id("1"); // 2.创建user对象 User user = new User(); user.setAge(18); user.setName("java从入门到入魔"); // 3.对象数据转json indexRequest.source(JSON.toJSONString(user), XContentType.JSON); // 4.执行请求 IndexResponse response = this.client.index(indexRequest, RequestOptions.DEFAULT); System.out.println(response.status()); // 返回操作的状态,初次是CREATED,后续修改返回OK System.out.println(response.toString()); } /** * 获取文档,判断是否存在 * * @throws IOException */ @Test public void docExist() throws IOException { //1.创建索引请求对象 GetRequest getRequest = new GetRequest("bie_index", "2"); //不获取返回的_source上下文,效率高 getRequest.fetchSourceContext(new FetchSourceContext(false)); //不排序 getRequest.storedFields("_none_"); // 2.执行请求 boolean exists = this.client.exists(getRequest, RequestOptions.DEFAULT); System.out.println(exists); }
/** * 获取文档信息 */ @Test public void getDoc() throws IOException { //1.创建索引请求对象 GetRequest getRequest = new GetRequest("bie_index", "1"); //2.执行请求 GetResponse response = this.client.get(getRequest, RequestOptions.DEFAULT); //3.获取文档内容 String sourceAsString = response.getSourceAsString(); System.out.println(sourceAsString); } /** * 更新文档信息 */ @Test public void updateDoc() throws IOException { //1.创建 更新索引请求对象 UpdateRequest updateRequest = new UpdateRequest("bie_index", "1"); updateRequest.timeout(TimeValue.timeValueSeconds(1)); //2.封装修改数据 UpdateRequest request = updateRequest.doc(JSON.toJSONString(new User().setName("哈哈 java")), XContentType.JSON); //3.执行请求 UpdateResponse response = this.client.update(request, RequestOptions.DEFAULT); System.out.println(response); } /** * 删除文档信息 */ @Test public void deleteDoc() throws IOException { DeleteRequest deleteRequest = new DeleteRequest("bie_index", "qVMa-oQBSvq_7IxZDk-f"); deleteRequest.timeout(TimeValue.timeValueSeconds(1)); DeleteResponse response = this.client.delete(deleteRequest, RequestOptions.DEFAULT); System.out.println(response.status()); }
/** * 批量 操作数据 */ @Test public void bulkDoc() throws IOException { BulkRequest bulkRequest = new BulkRequest(); bulkRequest.timeout(TimeValue.timeValueSeconds(10)); //数据越多,设置操作时间越大 List<User> users = Arrays.asList(new User("bie", 18), new User("bie3", 28)); for (int i = 0; i < users.size(); i++) { bulkRequest.add(new IndexRequest("bie_index") .id(String.valueOf(i + 1)) .source(JSON.toJSONString(users.get(i)), XContentType.JSON)); } BulkResponse response = this.client.bulk(bulkRequest, RequestOptions.DEFAULT); System.out.println(response.status()); }
常用搜索
/** * 搜索 * 常用查询操作:. * <p> * 精确查询:TermQueryBuilder * 全匹配查询:MatchAllQueryBuilder * 分页:sourceBuilder.from();sourceBuilder.size() * 高亮:sourceBuilder.highlighter() */ @Test public void searchDoc() throws IOException { SearchRequest searchRequest = new SearchRequest("bie_index"); //构建搜索条件 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); //QueryBuilders快速构建查询条件。 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", 18); sourceBuilder.query(termQueryBuilder); sourceBuilder.timeout(TimeValue.timeValueSeconds(1)); searchRequest.source(sourceBuilder); SearchResponse response = this.client.search(searchRequest, RequestOptions.DEFAULT); System.out.println(JSON.toJSONString(response.getHits())); for (SearchHit hit : response.getHits().getHits()) { System.out.println(JSON.toJSONString(hit.getSourceAsMap())); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。