开源的高扩展的分布式搜索引擎
环境安装
安装可视化界面 es head插件
- 下载地址 https://githab.com/mobz/elasticsearch-head/
- cnpm install 下载依赖(需要node.js环境)
- npm run start 启动服务
启动命令
npm run start
C:\MySpace\Environment\Elasticsearch\elasticsearch-head-master\elasticsearch-head-master>npm run start
> elasticsearch-head@0.0.0 start
> grunt server
Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100
- 解决跨域问题
..\elasticsearch-7.6.1\config\elasticsearch.yml 中新增配置
配置内容:
http.cors.enabled: true
http.cors.allow-origin: "*"
重启服务 双击bin目录下的enasticsearch.bat重启
通过 9100端口访问
安装kibana
地址:https://www.elastic.co/cn/elasticsearch/
解压 启动(双击.bat)
默认端口:5601
概念
elasticsearch层级
索引
表(已弃用)
文档
- 字段
天然支持分布式:es中存在分片的概念
使用倒排索引
倒排索引
文档id | 内容 |
---|---|
1 | 小明 |
2 | 小明 |
3 | 小明,小红 |
4 | 小红 |
倒排索引
内容 | 索引 |
---|---|
小明 | 1,2,3 |
小红 | 3,4 |
通过文档中的内容生成倒排索引,提高查询效率。例如查询小红,通过索引得知在id为3和4中存在相关内容,那么就只会在这两个文档中查找。
IK分词器
ik提供了两种分词算法ik_smart和ik_max_word其中ik_smart为最少切分,ik_max_word为最细粒度划分。
下载安装
地址:https://github.com/medcl/elasticsearch-analysis-ik
解压到es的plugins目录下
重启es
[2022-01-16T17:25:24,441][INFO ][o.e.p.PluginsService ] [LAPTOP-NGE1V8E1] loaded plugin [analysis-ik]
查看加载的插件
C:\MySpace\Environment\Elasticsearch\elasticsearch-7.6.1\bin>elasticsearch-plugin list
future versions of Elasticsearch will require Java 11; your Java version from [C:\MySpace\Environment\jdk\jre] does not meet this requirement
elasticsearch-analysis-ik-7.6.1
分词测试
基本操作
数据类型
字符串类型
- text keyword
数值类型
- long, integer, short ,byte ,double ,float, half float, scaled float
日期类型
- date
布尔类型
- boolean
二进制类型
- binary
语法
方法 | restful请求路径 | 描述 |
---|---|---|
PUT | localhost:9200/索引名/类型名/文档id | 创建文档(指定id) |
POST | localhost:9200/索引名/类型名 | 创建文档(随机id) |
POST | localhost:9200/索引名/类型名/文档id/_update | 修改文档 |
DELETE | localhost:9200/索引名/类型名/文档id | 删除文档 |
GET | localhost:9200/索引名/类型名/文档id | 通过文档id查询 |
POST | localhost:9200/索引名/类型名/文档id/_search | 查询所有数据 |
新增
创建索引规则
PUT /索引名
{
"mappings": {
"properties": {
"字段名":{
"type": "字段类型"
},
"字段名":{
"type": "字段类型"
}
}
}
}
例:
PUT /test2
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "integer"
}
}
}
}
获取所以规则
GET test2
新增数据
# PUT /索引名称/类型名/id
{请求体}
例:
PUT /test1/_doc/1
{
"name":"铁柱",
"sex":"男"
}
修改
PUT /索引名/类型名/id #修改会覆盖所有的字段
{请求体}
例:
PUT /test1/_doc/3
{
"name":"铁柱",
"sex":"男"
}
POST /索引名/_update/id #只会修改指定字段的值
{请求体}
例:
POST /test1/_update/1
{
"doc":{
"name":"狗蛋",
}
}
删除
DELETE /索引名/类型名/id #删除数据
DELETE 索引名 #删除索引
例:
DELETE /test1/_doc/2
DELETE test
查询
GET test1/_doc/1 #通过文档id查询
复合查询
语法
match只能单条件查询
_source 展示字段
sort 排序
from size 分页
hightlight 高亮展示
GET 索引/表/_search
{
"query":{
"match":{
"字段":"值"
}
},
"_source":["展示字段"],
"sort":[
{
"排序字段":{
"order":"排序方式" #desc asc
}
}
],
"from": 开始位置的下标, #从0开始
"size":返回数据量
}
例:
GET person/_doc/_search
{
"query":{
"match":{
"name":"铁柱"
}
},
"_source":["age"],
"sort":[
{
"age":{
"order":"desc"
}
}
],
"from":0,
"size":1
}
match与term
match可以通过分词进行模糊查询
term 只会进行精确匹配 但是会使用倒排索引 效率更高
布尔值查询(可以实现多条件查询)
must 且操作 查询满足所有条件的数据
should 或操作 查询满足其中一项条件的数据
must_not 非操作 查询不满足条件的数据
GET 索引/表/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"字段":"值"
}
},
{
"match":{
"字段":"值"
}
}
]
}
}
}
例:
GET person/_doc/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"铁柱"
}
},
{
"match":{
"age":1
}
}
]
}
}
}
过滤器
filter 进行数据过滤
gt 大于 lt小于 gte大于等于 lte 小于等于
GET person/_doc/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"翠花"
}
}
],
"filter":{
"range":{
"age":{
"gt":10,
"lt":50
}
}
}
}
}
}
扩展命令
GET _cat/health #查看健康值
GET _cat/indices?v #
集成SpringBoot
springboot文档地址 https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.rest
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置
@Configuration
public class ElacticSearchConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
索引操作
@Qualifier(value = "elasticsearchClient")
@Autowired
private RestHighLevelClient client;
/**
* 创建索引
* @throws IOException
*/
@Test
public void createIndex() throws IOException {
//创建索引请求
CreateIndexRequest index = new CreateIndexRequest("test_index");
//客户端执行请求 获取响应
CreateIndexResponse createIndexResponse = client.indices().create(index, RequestOptions.DEFAULT);
}
/**
* 判断索引是否存在
* @throws IOException
*/
@Test
void indexExist() throws IOException {
GetIndexRequest request = new GetIndexRequest("test_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
}
/**
* 删除索引
* @throws IOException
*/
@Test
void indexDelete() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("test_index");
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
}
文档操作
@Qualifier(value = "elasticsearchClient")
@Autowired
private RestHighLevelClient client;
/**
* 插入文档
* @throws IOException
*/
@Test
void createDoc() throws IOException {
User user = new User("小明",15);
IndexRequest request = new IndexRequest("test_index");
//拼装请求
//添加id
request.id("111");
//添加内容
request.source(JSON.toJSONString(user), XContentType.JSON);
//设置过期时间
request.timeout(TimeValue.timeValueSeconds(1));
//执行请求
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(request.toString());
}
/**
* 判断文档是否存在
* @throws IOException
*/
@Test
void existDoc() throws IOException {
GetRequest request = new GetRequest("test_index");
request.id("111");
//不获取返回的_source上下文
request.fetchSourceContext(new FetchSourceContext(false));
//判断文档是否存在
boolean exists = client.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
/**
* 获取文档信息
*/
@Test
void getDoc() throws IOException {
GetRequest request = new GetRequest("test_index");
request.id("111");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSource());
}
/**
* 更新文档
*/
@Test
void updateDoc() throws IOException {
UpdateRequest request = new UpdateRequest("test_index","111");
request.timeout(TimeValue.timeValueSeconds(1L));
User user = new User("小明", 25);
request.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
/**
* 删除文档记录
*/
@Test
void deleteDoc() throws IOException {
DeleteRequest request = new DeleteRequest("test_index", "111");
request.timeout(TimeValue.timeValueSeconds(1L));
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
批量操作
/**
* 批量插入数据
*/
@Test
void insertManyDoc() throws IOException {
BulkRequest request = new BulkRequest();
request.timeout(TimeValue.timeValueSeconds(10L));
ArrayList<User> users = new ArrayList<>();
users.add(new User("用户1",1));
users.add(new User("用户2",2));
users.add(new User("用户3",3));
for (int i = 0; i < users.size(); i++) {
//插入时使用IndexRequest 批量删除替换为DeleteRequest 批量更新使用UpdateRequest即可
request.add(new IndexRequest("test_index").id(String.valueOf(i)).source(JSON.toJSONString(users.get(i+1)),XContentType.JSON));
}
BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
System.out.println(bulk.status());
}
查询
/**
* 查询
*/
@Test
void testSearch() throws IOException {
SearchRequest request = new SearchRequest(indexName);
//构架搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查询条件
//QueryBuilders.termQuery 精确匹配
//QueryBuilders.matchAllQuery 匹配所有
TermQueryBuilder queryBuilder = QueryBuilders.termQuery("age", 2);
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
request.source(searchSourceBuilder);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//打印结果
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}