目前市面比较常用的搜索引擎,都是基于Lucene的搜索服务器,用Java开发而成
elasticsearch提供了一个分布式多用户能力的全文搜索引擎,索引方式:json
Elasticsearch核心概念
- 全文检索
- 全文索引
- 接近实时
- 索引
- 倒排索引
- 类型
- 文档
- 分片和复制
- 集群
- 节点
PS:倒排索引的出现,弱化了type的概念和功能,且在elasticsearch 7.x中已经删除了type的概念,也就是没有表的概念了
安装步骤省略...
安装过程中遇到的问题
- mac 本机安装时启动报错
解决方案:es版本和jdk版本不匹配
- 启动报错:could not find java in JAVA_HOME at $(/usr/libexec/java_home -v 11)/bin/java
解决方案:www.jianshu.com/p/9b334e42a…
- 其他问题暂时未记录(在linux系统上还会有一个基本的问题,es处于安全考虑,要用非root用户启动,root账户启动报错,mac本机未遇到该问题)
了解说明:因为默认登录的管理员和root是有区别的,默认登录的就是普通管理员用户,所以没出现该错误
- 后台启动时报警告( ./elasticsearch -d):Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
未进行影响正常启动,大致百度了下原因
解决方案:blog.csdn.net/m0_60264772…
- 启动成功测试
索引操作(index)
创建索引:(索引==mysql中的表)PUT,索引名称只能小写
获取索引信息:GET
查看ES中所有索引:GET,请求入参改变:_cat/indices?v 参数v相当于格式化了下,不传也可以
删除索引:DELETE
文档操作(doc)
创建文档(插入数据):POST,索引名/_doc
自定义ID:索引名/_create/id 等同于 索引名/_doc/id
区别:_create/id 如果数据重复会报错 ---幂等性,所以在指定ID的时候也可使用PUT请求(具有幂等性)
_doc/id 如果ID一样内容不一样则update
自定义ID好处:便于查询,不传则随机生成ID,当然es的出现查询也不会通过ID去查询
查看文档(数据):单条
查询该索引下所有文档:_search
根据蛋哥单个属性条件查询:GET:索引名/_search,入参 ---推荐使用方式
{
"query":{
"match":{
"属性名1":"value"
}
}
}
查询所有:GET:索引名/_search,入参 ---推荐使用方式
入参区别:match_all
分页查询:
指定返回数据源的属性:
排序:
多条件查询入参:bool
- must===> AND
- should===> OR
- 范围查询:filter
文档修改:
- 完全修改 PUT:_doc/id
- 局部修改 POST:_update/id 入参格式变化
{
"doc":{
"属性名1":"修改的值1",
"属性名2":"修改的值2"
}
}
文档删除:DELETE 索引名/_doc/id
多次删除无效,不会报错,返回结果集中会告知not_found
javaAPI操作
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.1</version>
</dependency>
package com.example.demo.controller.esTest;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.cluster.metadata.MappingMetadata;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@Slf4j
//@XSlf4j
public class EsTestCOontroller {
public static void main(String[] args) throws IOException {
// 创建连接 scheme可不传,不传则使用默认的 默认的是多少呢?一会测试一下
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("124.222.1.237", 9200,
"http")));
//创建索引
// createIndex(client);
// 删除索引
// delIndex(client);
// 查询索引
getIndex(client);
// 关闭连接 此处练习先抛出异常
client.close();
}
/**
* 创建索引
*/
public static void createIndex(RestHighLevelClient client) throws IOException {
CreateIndexRequest indexRequest = new CreateIndexRequest("test_two");
CreateIndexResponse indexResponse = client.indices().create(indexRequest, RequestOptions.DEFAULT);
log.info("创建响应:{},响应结果标识:{}", JSONObject.toJSONString(indexResponse),indexResponse.isAcknowledged());
}
/**
* 删除索引
*/
public static void delIndex(RestHighLevelClient client) throws IOException {
DeleteIndexRequest indexRequest = new DeleteIndexRequest("test");
AcknowledgedResponse delete = client.indices().delete(indexRequest, RequestOptions.DEFAULT);
log.info("创建响应:{},响应结果标识:{}", JSONObject.toJSONString(delete),delete.isAcknowledged());
}
/**
* 修改索引:elasticsearch不可 修改索引,只能进行获取原来的index映射再进行针对性的修改,并创建为新index,再将原来的index数据迁移到新index上
*/
public static void modifyIndex(RestHighLevelClient client) {
}
/**
* 查看索引
*/
public static void getIndex(RestHighLevelClient client) throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest("idx");
getIndexRequest.includeDefaults(true);
GetIndexResponse getIndexResponse = client.indices().get(getIndexRequest, RequestOptions.DEFAULT);
MappingMetadata indexMappings = getIndexResponse.getMappings().get("idx");
log.info("indexMappings===>:{}", JSONObject.toJSONString(indexMappings));
Map<String, Object> indexTypeMappings = indexMappings.getSourceAsMap();
log.info("indexTypeMappings===>:{}", JSONObject.toJSONString(indexTypeMappings));
List<AliasMetadata> indexAliases = getIndexResponse.getAliases().get("idx");
log.info("indexAliases===>:{}", JSONObject.toJSONString(indexAliases));
String numberOfShardsString = getIndexResponse.getSetting("idx", "idx.number_of_shards");
log.info("numberOfShardsString===>:{}", JSONObject.toJSONString(numberOfShardsString));
Settings indexSettings = getIndexResponse.getSettings().get("idx");
log.info("indexSettings===>:{}", indexSettings.toString());
Integer numberOfShards = indexSettings.getAsInt("idx.number_of_shards", null);
log.info("numberOfShards===>:{}", JSONObject.toJSONString(numberOfShards));
TimeValue time = getIndexResponse.getDefaultSettings().get("idx").getAsTime("idx.refresh_interval", null);
log.info("time===>:{}", JSONObject.toJSONString(time));
}
}
查询index时遇到的问题:
- 不能直接将GetIndexResponse进行jsonToString,否则会报错
@Configuration
//@ConfigurationProperties(prefix = "这里配置什么前缀,则在配置文件中给该类赋值的就必须是该前缀,@Value 属性取值则也是结合这个来取的")
public class EsConfiguration {
// ip或者dns
private static String esIp = "124.222.1.237";
// 端口
private static int port = 9200;
// 请求方式
private static String scheme = "http";
@Bean
public RestHighLevelClient getClient(){
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost(esIp, port,
scheme)));
return client;
}
}
package com.example.demo;
import com.example.demo.configuration.EsConfiguration;
import com.example.demo.controller.esTest.EsDocController;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.IOException;
@SpringBootTest
class DemoApplicationTests {
@Resource
private EsDocController esDocController;
@Resource
private EsConfiguration esConfiguration;
@Test
void contextLoads() throws IOException {
RestHighLevelClient client = esConfiguration.getClient();
// 插入doc
// esDocController.insertDoc(client,"lucky");
// 修改doc 修改不存在的数据会报错 ElasticsearchStatusException
esDocController.modifyDoc(client,"lucky1","CTyKm4UBkZs9DeCwgnVV");
// 删除doc 删除不存在的则不会报错,也不会删除该索引下的所有数据
esDocController.delDoc(client,"lucky","CTyKm4UBkZs9DeCwgnVV");
//查询doc
esDocController.selectDoc(client,"lucky","d740bc06-957b-49c1-88b8-a31d9247e63a");
client.close();
}
}
package com.example.demo.controller.esTest;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.example.demo.configuration.EsConfiguration;
import com.example.demo.docModel.WestDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Controller;
import org.springframework.util.unit.DataUnit;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Random;
import java.util.UUID;
/**
* ES文档操作
*/
@Slf4j
@Controller
public class EsDocController {
@Resource
private EsConfiguration esConfiguration;
/**
* 创建索引并插入数据
* @throws IOException
*/
public void createDoc() throws IOException {
RestHighLevelClient client = esConfiguration.getClient();
CreateIndexRequest request = new CreateIndexRequest("lucky");
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
// 如果index创建成功则继续创建doc(文档) 正常业务中是先查询如果存在则直接创建数据,如果不存在则创建
if(Boolean.TRUE.equals(createIndexResponse.isAcknowledged())){
insertDoc(client,request.index());
}
client.close();
}
/**
* 插入数据doc
* @param client
* @param index
* @throws IOException
*/
public void insertDoc(RestHighLevelClient client,String index) throws IOException {
// 创建doc过程如下
IndexRequest indexRequest = new IndexRequest();
// 如果ID不指定则会自动生成一个
indexRequest.index(index).id(UUID.randomUUID().toString());
// indexRequest.index(request.index());
WestDTO westDTO = WestDTO.builder()
.age(18)
.address("重庆渝北区")
.gender(1)
.username(index+ System.currentTimeMillis())
.build();
String westJson = JSONObject.toJSONString(westDTO);
indexRequest.source(westJson, XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
log.info("插入数据成功响应:{}",JSONObject.toJSONString(indexResponse));
}
/**
* 修改doc数据 修改数据需要提前判断数据是否存在,否则会报错
* @param client
* @param indexName
* @param docId
* @throws IOException
*/
public void modifyDoc(RestHighLevelClient client,String indexName,String docId) throws IOException {
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index(indexName).id(docId).doc(XContentType.JSON, "address", "四川省成都市xx区","age", 98);
UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
log.info("修改数据成功响应:{}",JSONObject.toJSONString(update));
}
/**
* 删除数据
*/
public void delDoc(RestHighLevelClient client,String indexName,String docId) throws IOException{
DeleteRequest deleteRequest = new DeleteRequest();
DeleteRequest id = deleteRequest.index(indexName).id(docId);
DeleteResponse delete = client.delete(id, RequestOptions.DEFAULT);
log.info("删除doc===>{}",JSONObject.toJSONString(delete));
}
public void selectDoc(RestHighLevelClient client,String indexName,String docId) throws IOException {
GetRequest getRequest = new GetRequest();
getRequest.index(indexName).id(docId);
GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
log.info("查询单个doc===>{}",JSONObject.toJSONString(response));
}
}