ElasticSearch安装
声明:最低要求JDK8,必须保证ElasticSearch的版本与Java的核心jar包版本对应。
下载
windows安装
1、解压
2、熟悉目录
bin 启动文件
config 配置文件
1og4j2 日志配置文件
jvm.options java 虚拟机相关的配置(默认启动占1g内存默认在20行左右,内容不够需要自己调整)
elasticsearch.ym1 elasticsearch 的配置文件! 默认9200端口! 跨域!
1ib 相关jar包
logs 日志
modules 功能模块
plugins 插件
3、启动
4、访问测试
安装可视化界面es head的插件
1、下载地址:https://github.com/mobz/elasticsearch-head
2、启动
npm install
npm run start
3、连接测试发现,存在跨域问题,需在es配置文件elasticsearch.yml中进行配置
http.cors.enabled: true
http.cors.allow-origin: "*"
4、重启es后再次连接,此时连接成功
了解ELK
ELK是Elasticsearch、Logstash、 Kibana三大开源框架首字母大写简称,市面上也被成为Elastic Stack,其中Elasticsearch是一个基于Lucene分布式、通过Restful方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用Elasticsearch作为底层支持框架,可见Elasticsearch提供的搜索能力确实强大,市面上很多时候我们简称Elasticsearch为es.Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等 )。Kibana可以将elasticsearch的数据通过友好的页面展示出来,提供实时分析的功能
市面上很多开发只要提到ELK能够一致说出它是一个日志分析架构技术栈总称,但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据分析和收集的场景,日志分析和收集只是更具有代表性。并非唯一性。
安装Kibana
Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板( dashboard)实时显示Elasticsearch查询动态。设置Kibana非常简单,无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。
官网:https://www.elastic.co/cn/kibana
Kibana版本要和 Es版本一致!
启动测试
1、解压后的目录
2、启动
3、访问测试
4、开发工具
之后所有的操作都在这里编写。
5、汉化,修改kibana配置即可
6、重启即可
IK分词器插件
什么是IK分词器?
分词 即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱狂神”会被分为"我""爱""狂""神”,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。
如果要使用中文,建议使用ik分词器。
IK提供了两个分词算法:ik_smat 和 ik_max_word,其中 ik_smart 为最少切分,ik_max_word为最细粒度划分!一会我们测试!
安装
1、https://github.com/medcl/elasticsearch-analysis-ik
2、下载完毕之后,放入到我们的elasticsearch插件即可!
3、重启观察ES,可以看到ik分词器被加载了
4、elasticsearch-plugin list 可以通过这个命令查看加载进来的插件
5、使用kibana测试!
查看不同的分词效果
其中 ik_smart 为最少切分
ik_max_word 为最细粒度划分!穷尽词库的可能!字典!
输入 超级喜欢狂神说Java
发现问题:狂神说三个字被拆开了!
这种自己需要的词,需要我们自己加到我们的分词器字典中!
ik分词器增加自己的配置!
重启es,看细节!
再次测试,查看效果!
Rest风格说明
一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
基本Rest命令说明:
索引的基本操作
创建索引
PUT /索引名/类型名/文档id # 类型名被新版本弃用了
{
请求体
}
这样就完成了索引的创建
字段数据类型
字符串类型
- text 、keyword
数值类型
- long,integer,short,byte,double,float,half float,scaled float
日期类型
- date
布尔值类型
- boolean
二进制类型
- binary
获取索引的信息
1、指定字段的类型
2、获得这个规则,可以通过 GET 请求来获取具体的信息!
3、查看默认的类型信息
如果自己的文档字段没有指定,那么es 就会给我们默认配置字段类型!
扩展:通过 GET _cat/ 可以获得 es 的当前很多信息!
修改
1、使用PUT进行覆盖
2、使用post进行修改
删除索引
通过DELETE 命令实现删除
根据你的请求来判断是删除索引还是删除文档记录
关于文档的操作
基本操作
1、添加数据
PUT /xuebi/user/1
{
"name": "雪碧说",
"age": 23,
"desc": "一顿操作猛如虎,一看工资2500",
"tags": ["技术宅","温暖","直男"]
}
PUT /xuebi/user/2
{
"name": "张三",
"age": 3,
"desc": "法外狂徒",
"tags": ["交友","旅游","渣男"]
}
PUT /xuebi/user/3
{
"name": "李四",
"age": 30,
"desc": "mmp,不知道如何形容",
"tags": ["靓女","旅游","唱歌"]
}
2、获取数据 GET
3、更新数据 PUT
4、POST _update,推荐使用这种更新方式
简单的搜索!
GET xuebi/user/1
简单的条件查询,可以根据默认的映射规则,产生基本的查询!
复杂搜索操作
输出结果不想要那么多
我们之后使用java操作es,所有的方法和对象就是这里面的key!
排序
分页查询
数据下标和学的所有的数据结构一样,都是从0开始的!
布尔值查询
must,所有的条件都要符合。
should,满足一个条件即可。
must_not,不满足下面条件的。
过滤器filter
- gt 大于
- gte 大于等于
- lt 小于
- lte 小于等于
匹配多个条件
精确查询
term 查询是直接通过倒排索引指定的词条进行精确的查找的!
关于分词:
- term,直接查询精确的
- match,会使用分词器解析
两个类型 text keyword
多个值匹配精确查询
高亮查询
集成Spring Boot
找官方文档
https://www.elastic.co/guide/index.html
1、找到原生的依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.9</version>
</dependency>
2、找对象
3、分析这个类中的方法即可!
配置基本的项目
一定要保证我们导入的依赖和我们 es 的版本一致
具体的api测试
1、创建索引
2、获取索引
3、删除索引
4、创建文档
5、crud文档
package com.xuebi;
import com.alibaba.fastjson.JSON;
import com.xuebi.pojo.User;
import org.apache.lucene.util.QueryBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
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.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
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.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
/**
* springboot 集成 es 测试
*/
@SpringBootTest
class XuebiEsApiApplicationTests {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
// 同上
// @Autowired
// private RestHighLevelClient restHighLevelClient;
//测试索引的创建 Request
@Test
void testCreateIndex() throws IOException {
//1、 创建索引请求
CreateIndexRequest request = new CreateIndexRequest("xuebi_index");
//2、 客户端执行请求 IndicesClient, 请求后获得响应
CreateIndexResponse response = client.indices().create(request,RequestOptions.DEFAULT);
System.out.println(response);
}
// 测试获取索引,判断是否存在
@Test
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("xuebi_index");
boolean response = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(response);
}
// 测试删除索引
@Test
void testDelete() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("xuebi_index");
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
}
// 测试添加文档
@Test
void testAddDocument() throws IOException {
User user = new User("雪碧说", 3);
IndexRequest request = new IndexRequest("xuebi_index");
request.id("1");
// 下面两者都是过期时间 两者都可以使用
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
//将数据放入请求 json
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response.toString());
System.out.println(response.status()); //状态
}
// 获取文档,判断是否存在
@Test
void testIsExists() throws IOException {
GetRequest request = new GetRequest("xuebi_index", "1");
// 不获取返回的_source上下文
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
boolean response = client.exists(request, RequestOptions.DEFAULT);
System.out.println(response);
}
// 获取文档信息
@Test
void testGetDocument() throws IOException {
GetRequest request = new GetRequest("xuebi_index", "1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString()); //打印文档的内容
System.out.println(response); //返回全部内容,和命令是一样的
}
// 更新文档的信息
@Test
void testUpdateRequest() throws IOException {
UpdateRequest request = new UpdateRequest("xuebi_index", "1");
request.timeout("1s");
User user = new User("雪碧说java", 18);
request.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
// 删除文档
@Test
void testDeleteRequest() throws IOException {
DeleteRequest request = new DeleteRequest("xuebi_index", "1");
request.timeout("1s");
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
// 批量插入数据
@Test
void testBulkRequest() throws IOException {
BulkRequest request = new BulkRequest();
request.timeout("10s");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("xuebi1",3));
userList.add(new User("xuebi2",3));
userList.add(new User("xuebi3",3));
userList.add(new User("kele1",3));
userList.add(new User("kele1",3));
userList.add(new User("kele1",3));
//批处理请求
for (int i = 0; i < userList.size(); i++) {
//批量更新和删除,就在这里修改对应的请求就可以了
request.add(new IndexRequest("xuebi_index")
.id(""+i+1)
.source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
}
BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.hasFailures()); //是否失败 flase就代表成功了
}
// 查询
// SearchRequest 搜索请求
// SearchSourceBuilder 条件构造
// HighlightBuilder 构建高亮
// TermQueryBuilder 精确查询
// MatchAllQueryBuilder
@Test
void testSearch() throws IOException {
SearchRequest request = new SearchRequest("xuebi_index");
// 构建搜索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 查询条件,我们可以使用 QueryBuilders 工具来实现
// QueryBuilders.termQuery() 精确
// QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder queryBuilder = QueryBuilders.termQuery("name", "kele1");
// MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
sourceBuilder.query(queryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(response.getHits()));
System.out.println("=========================================");
for (SearchHit documentFields : response.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
实战
爬取数据
爬取数据:(获取请求返回的页面信息,筛选出我们想要的数据就可以了)
jsoup包!
1、导入依赖
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.4</version>
</dependency>
2、分析网页,创建工具类HtmlParseUtil
package com.xuebi.utils;
import com.xuebi.pojo.Content;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@Component
public class HtmlParseUtil {
// public static void main(String[] args) throws IOException {
// new HtmlParseUtil().parseJD("苹果14").forEach(System.out::println);
// }
public List<Content> parseJD(String keywords) throws IOException {
//获取请求 https://search.jd.com/Search?keyword=java
//前提,需要联网
String url = "https://search.jd.com/Search?keyword="+keywords;
//解析网页 Jsoup返回的Document就是浏览器的Document对象
Document document = Jsoup.parse(new URL(url), 30000);
Element element = document.getElementById("J_goodsList");
//获取所有的li元素
Elements elements = element.getElementsByTag("li");
//获取元素中的内容,这里每个el就是每个li标签了!
ArrayList<Content> goodsList = new ArrayList<>();
for (Element el : elements) {
// 关于这种图片特别多的网站,所有的图片都是延迟加载的!
String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");
String price = el.getElementsByClass("p-price").eq(0).text();
String title = el.getElementsByClass("p-name").eq(0).text();
Content content = new Content();
content.setImg(img);
content.setPrice(price);
content.setTitle(title);
goodsList.add(content);
}
return goodsList;
}
}
业务编写
package com.xuebi.service;
import com.alibaba.fastjson.JSON;
import com.xuebi.pojo.Content;
import com.xuebi.utils.HtmlParseUtil;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
//业务编写
@Service
public class ContentService {
@Autowired
private RestHighLevelClient restHighLevelClient;
//1、解析数据放到 es 索引中
public Boolean parseContent(String keywords) throws IOException {
//查询数据
List<Content> contents = new HtmlParseUtil().parseJD(keywords);
//把查询到的数据放入 es 中
BulkRequest request = new BulkRequest();
request.timeout("2s");
for (int i = 0; i < contents.size(); i++) {
request.add(
new IndexRequest("jd_goods")
.source(JSON.toJSONString(contents.get(i)),XContentType.JSON));
}
BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
return !response.hasFailures();
}
//2、获取这些数据实现搜索功能
public List<Map<String,Object>> searchPage(String keyWord,int pageNo,int pageSize) throws IOException {
if (pageNo<=1){
pageNo=1;
}
//条件搜索
SearchRequest request = new SearchRequest("jd_goods");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//分页
sourceBuilder.from(pageNo);
sourceBuilder.size(pageSize);
//精准匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyWord);
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//执行搜索
request.source(sourceBuilder);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
//解析结果
ArrayList<Map<String,Object>> list = new ArrayList<>();
for (SearchHit hit : response.getHits().getHits()) {
list.add(hit.getSourceAsMap());
}
return list;
}
//3、获取这些数据实现搜索高亮功能
public List<Map<String,Object>> searchPageHighlight(String keyWord,int pageNo,int pageSize) throws IOException {
if (pageNo<=1){
pageNo=1;
}
//条件搜索
SearchRequest request = new SearchRequest("jd_goods");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//分页
sourceBuilder.from(pageNo);
sourceBuilder.size(pageSize);
//精准匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyWord);
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.requireFieldMatch(false);//多个高亮显示
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
sourceBuilder.highlighter(highlightBuilder);
//执行搜索
request.source(sourceBuilder);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
//解析结果
ArrayList<Map<String,Object>> list = new ArrayList<>();
for (SearchHit hit : response.getHits().getHits()) {
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField title = highlightFields.get("title");
Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
//解析高亮的字段,将原来的字段换成我们的高亮字段即可
if(title!=null){
Text[] fragments = title.fragments();
String n_title="";
for (Text text : fragments) {
n_title += text;
}
sourceAsMap.put("title",n_title);
}
list.add(sourceAsMap);
}
return list;
}
}
请求编写
package com.xuebi.controller;
import com.xuebi.service.ContentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@RestController
public class ContentController {
@Autowired
private ContentService contentService;
@GetMapping("/parse/{keyword}")
public Boolean parse(@PathVariable("keyword") String keyword) throws IOException {
return contentService.parseContent(keyword);
}
// @GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
// public List<Map<String,Object>> search(@PathVariable("keyword") String keyword,
// @PathVariable("pageNo") int pageNo,
// @PathVariable("pageSize") int pageSize) throws IOException {
//
// return contentService.searchPage(keyword, pageNo, pageSize);
//
// }
//高亮搜索
@GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
public List<Map<String,Object>> search(@PathVariable("keyword") String keyword,
@PathVariable("pageNo") int pageNo,
@PathVariable("pageSize") int pageSize) throws IOException {
return contentService.searchPageHighlight(keyword, pageNo, pageSize);
}
}
标签:Elaticsearch,org,request,elasticsearch,new,import,response
From: https://www.cnblogs.com/gc5132/p/17298373.html