文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
1、elasticsearch安装启动
看见访问localhost:9200能见到for search说明正常
2、安装head插件
elasticsearch的可视化工具 端口为9100
3、整合kibana
http://localhost:5601/app/kibana kibana以来node.js,需要安装
kibana汉化,在kibana.yml中加i18n.locale: “zh-CN”
kibana.yml也可以配置elasticsearch服务的地址和端口等。
4、与java整合
与springboot整合
1、添加jar包
2、yml添加配置文件
cluster-nodes: 127.0.0.1:9300 # es的连接地址及端口号
cluster-name: elastic # es集群的名称
这里为什么是9300端口不是9200端口呢?
9200是给http协议通讯用的,9300是集群中通讯用的用的tcp协议,RPC框架都是用的tcp协议。
两者协议区别:
概念
正排索引
也就是一个id(索引)对应一条数据传统的类似mysql数据库,查询时通过索引能快速查询到数据,但是模糊查询呢,只能通过遍历数据库,一个个去匹配,严重影响效率。
倒排索引
文档数据去查询id的索引,通过数据“student”的查询到索引为1,2,3
elasticsearch基本操作
1)GET:获取请求对象的当前状态。
2)POST:改变对象的当前状态。
3)PUT:创建一个对象。
4)DELETE:销毁对象。
5)HEAD:请求获取对象的基础信息。
1、索引操作
PUT(幂等)
创建索引(等同于创建数据库)http://127.0.0.1:9200/shopping PUT方式
GET
查看索引 http://127.0.0.1:9200/shopping GET方式
查看所有索引 http://127.0.0.1:9200/_cat/indices?v 类似(show tables)
DELETE(幂等)
删除索引 http://127.0.0.1:9200/shopping DELETE 方式
POST
向索引添加文档或者修改文档 http://127.0.0.1:9200/shopping/_doc
返回数据解析
{
"_index"【索引】: "shopping",
"_type"【类型-文档】: "_doc",
"_id"【唯一标识】: "Xhsa2ncBlvF_7lxyCE9G", #可以类比为 MySQL 中的主键,随机生成
"_version"【版本】: 1,
"result"【结果】: "created", #这里的 create 表示创建成功
"_shards"【分片】: {
"total"【分片 - 总数】: 2,
"successful"【分片 - 成功】: 1,
"failed"【分片 - 失败】: 0
},
"_seq_no": 0,
"_primary_term": 1
}
这里的文档_type是死的 只能写_doc,后面可以添加自定义id比如:
http://127.0.0.1:9200/shopping/_doc /123
这样es系统的_id就是123了
注意:put和post区别
应为每次post请求不指定id的话都会创建一个文档并返回一个文档id,多次请求返回的id,这个id是es自动生成的,不是操作的同一个文档。
put请求因为是幂等的,发送创建文档的话只能针对同一个id的文档,所以这里不能使用,前面创建索引的话他是同一个所以可以使用。http://127.0.0.1:9200/shopping/_doc /123 PUT方式,这样的话可以访问。
2、文档操作
修改和新增文档
指定id的创建文档(不指定id会自动生成一个id)
http://127.0.0.1:9200/shopping(索引名称)/_doc(文档类型只能是_doc)/123(文档id) POST/PUT方式
http://127.0.0.1:9200/shopping/_doc/123 POST方式
这里注意:json格式发送的话会整体覆盖。
如果只想修改文档中的一个字段
http://127.0.0.1:9200/shopping/_update/123 POST方式
这里只会修改body体中的字段
删除文档
http://127.0.0.1:9200/shopping/_doc/123 DELETE方式
根据条件删除多个文档
http://127.0.0.1:9200/shopping/_delete_by_query POST方式
body中添加条件
{
"query":{
"match":{
"price":4000.00
}
}
}
查询文档(重点)
指定id查询
http://127.0.0.1:9200/shopping(索引名称)/_doc(文档类型只能是_doc)/123(文档id) GET方式
http://127.0.0.1:9200/shopping/_search GET方式
{
"query" : {
//查询所有
"match_all" : {}
//条件查询
"match":{
"price":4000.00
}
}
分页排序查询
{
"query" : {
//查询所有
"match_all" : {}
},
"from":0,
"size":2
//需要显示的key内容
"_source":{"title"}
//根据price降序排序
"sort":{
"price":{
"order":"desc"
}
}
}
多条件查询过滤查询
{
"query" : {
"bool":{
//must表示必须都满足,should表示满足一个
"must"//"should":[
{
"match" : {
"category":"小米"
"category":"米"
}
},
{
"match" : {
"category":"华为"
}
}
],
//过滤查询price大于5000
"filter":{
"range":{
"price":{
"gt":5000
}
}
}
}
}
}
全文检索和完全匹配高亮查询
{
"query" : {
//全文检索
"match":{
//文档中没有小华为什么也能查询到?es默认做了分词,分别查询”小“和”华“
"category":"小华"
}
//完全匹配
"match_phrase":{
//这里只能查询到文档中有小华的文档了
"category":"小华"
}
//高亮查询
"highlight":{
//哪些字段需要高亮显示
"fields":{
"category":{}
}
}
}
聚合操作
{
//分组
"aggs":{
"price_group":{ //分组名称随意取
"terms":{
"field":"price" //分组字段
}
}
}
}
这里解释为什么不创建索引聚合会报错(text类型默认禁用Fieddata)
索引(类似数据库表的字段)
创建索引(也可以增加索引,但是不支持修改)
http://127.0.0.1:9200/student/_mapping post方式
{
"properties": {
"name":{
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": false
},
"age":{
"type": "long",
"index": false
}
} }
查看索引
http://127.0.0.1:9200/student/_mapping GET方式
类似数据库表的数据类型,你不创建的话es会默认给你个索引类型字段名:
索引的数据类型
type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
String 类型,又分两种:
text:可分词
keyword:不可分词,数据会作为完整字段进行匹配
Numerical:数值类型,分两类
基本数据类型:long、integer、short、byte、double、float、half_float
浮点数的高精度类型:scaled_float
Date:日期类型
Array:数组类型
Object:对象
其他属性
index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。
true:字段会被索引,则可以用来进行搜索
false:字段不会被索引,不能用来搜索
store:是否将数据进行独立存储,默认为 false
原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器。
整合java api
导入pom
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.6.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.1</version>
</dependency>
class EsstudyApplicationTests {
@Test
void contextLoads()throws Exception {
//连接
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//------------------------------------------------索引------------------------------------------------
//创建索引
// CreateIndexRequest request = new CreateIndexRequest("javauser");
// CreateIndexResponse createIndexResponse = esClient.indices().create(request, RequestOptions.DEFAULT);
//响应状态
// boolean acknowledged = createIndexResponse.isAcknowledged();
// System.out.println(acknowledged);
//查询索引
// GetIndexRequest request = new GetIndexRequest("user");
// GetIndexResponse getIndexResponse = esClient.indices().get(request, RequestOptions.DEFAULT);
// System.out.println(getIndexResponse.getAliases());
// System.out.println(getIndexResponse.getMappings());
// System.out.println(getIndexResponse.getSettings());
//删除索引
// DeleteIndexRequest request = new DeleteIndexRequest("user");
// AcknowledgedResponse delete = esClient.indices().delete(request, RequestOptions.DEFAULT);
// System.out.println(delete.isAcknowledged());
//------------------------------------------------文档------------------------------------------------
//文档增加数据
// IndexRequest request = new IndexRequest();
// request.index("user").id("1001"); //索引库和id
// User user = new User();
// user.setName("张三");
// user.setSex("男");
// user.setTel("das");
// user.setMoney((long)312);
// //必须转成json格式
// String userjson = JSON.toJSONString(user);
// request.source(userjson, XContentType.JSON);
// IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);
// System.out.println(response.getResult());
//修改文档
// UpdateRequest request = new UpdateRequest();
// request.index("user").id("1001"); //索引库和id
// request.doc(XContentType.JSON,"sex","女的");
// UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);
// System.out.println(response.getResult());
//文档查询
//1.创建请求对象
// GetRequest request = new GetRequest().index("user").id("1001");
// //2.客户端发送请求,获取响应对象
// GetResponse response = esClient.get(request, RequestOptions.DEFAULT);
// //3.打印结果信息
// System.out.println("_index:" + response.getIndex());
// System.out.println("_type:" + response.getType());
// System.out.println("_id:" + response.getId());
// System.out.println("source:" + response.getSourceAsString());
//删除文档
//创建请求对象
// DeleteRequest request = new DeleteRequest().index("user").id("1001");
// //客户端发送请求,获取响应对象
// DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
// //打印信息
// System.out.println(response.toString());
//------------------------------------------------批量操作------------------------------------------------
//批量新增
// BulkRequest request = new BulkRequest();
// request.add(new IndexRequest().index("user").id("1001").source(XContentType.JSON, "name", "zhangsan"));
// request.add(new IndexRequest().index("user").id("1002").source(XContentType.JSON, "name", "lisi"));
// request.add(new IndexRequest().index("user").id("1003").source(XContentType.JSON, "name", "wangwu"));
// //客户端发送请求,获取响应对象
// BulkResponse responses = esClient.bulk(request, RequestOptions.DEFAULT);
// //打印结果信息
// System.out.println("took:" + responses.getTook());
// System.out.println("items:" + responses.getItems());
//批量删除
// BulkRequest request = new BulkRequest();
// request.add(new DeleteRequest().index("user").id("1001"));
// request.add(new DeleteRequest().index("user").id("1002"));
// request.add(new DeleteRequest().index("user").id("1003"));
// //客户端发送请求,获取响应对象
// BulkResponse responses = esClient.bulk(request, RequestOptions.DEFAULT);
// //打印结果信息
// System.out.println("took:" + responses.getTook());
// System.out.println("items:" + responses.getItems());
//------------------------------------------------高级查询(分页,排序)------------------------------------------------
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 查询所有数据
// sourceBuilder.query(QueryBuilders.matchAllQuery());
//matchPhraseQuery 查询,查询条件为关键字 不会分词查询 不要用termQuery是个坑
// sourceBuilder.query(QueryBuilders.matchPhraseQuery("name", "果"));
//会根据'小' '米' '小米'分词查询
// sourceBuilder.query(QueryBuilders.matchQuery("category","小米"));
// 分页查询
// 当前页其实索引(第一条数据的顺序号),from
// sourceBuilder.from(0);
// 每页显示多少条 size
// sourceBuilder.size(2);
// 排序
// sourceBuilder.sort("price", SortOrder.ASC);
//查询字段过滤
// String[] excludes = {};
// String[] includes = {"title", "category"};
// sourceBuilder.fetchSource(includes, excludes);
//bool查询组合查询 matchQuery和matchPhraseQuery一个是分词查询,一个是精确的
// BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 必须包含
// boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("money", "100"));
// 一定不含
// boolQueryBuilder.mustNot(QueryBuilders.matchPhraseQuery("title", "小华"));
// 可能包含
// boolQueryBuilder.should(QueryBuilders.matchQuery("title", "小米手机"));
// sourceBuilder.query(boolQueryBuilder);
//范围查询
// RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("birth");
// 大于等于
// rangeQuery.gte("1992-11-12");
// 小于等于
// rangeQuery.lte("2000-11-12");
// sourceBuilder.query(rangeQuery);
//模糊查询
//这种模糊查询支持text和keyword格式,不过text加?不起作用(可能原因是中文做了分词),只能加*
// sourceBuilder.query(QueryBuilders.wildcardQuery("sex","男*"));
//这种模糊查询支持text和keyword格式 text格式中文默认只能搜索一个单词,大概原因是默认对text做了分词,搜索两个字段没法查询到。而keyword没有做分词,所以只能精确查询到。
//而且这里可以设置模糊度,默认是auto。
// sourceBuilder.query(QueryBuilders.fuzzyQuery("sex","男"));
//高亮
//构建高亮字段
// sourceBuilder.query(QueryBuilders.matchAllQuery());
// HighlightBuilder highlightBuilder = new HighlightBuilder();
// highlightBuilder.preTags("<font color='red'>");//设置标签前缀
// highlightBuilder.postTags("</font>");//设置标签后缀
// highlightBuilder.field("name");//设置高亮字段
//设置高亮构建对象
// sourceBuilder.highlighter(highlightBuilder);
//聚合查询
//最大
// sourceBuilder.aggregation(AggregationBuilders.max("maxMoney").field("money"));
//分组
// sourceBuilder.aggregation(AggregationBuilders.terms("sex_groupby").field("sex"));
// request.source(sourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
// 查询匹配
SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
//关闭客户端
esClient.close();
}
}