1.安装Elasticsearch
a.下载:从官网下载 Elasticsearch,地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch
b.启动:解压后,在 bin 目录打开 elasticsearch.bat 启动服务
c.访问:在浏览器中访问 http://127.0.0.1:9200/ 检查是否安装成功
注意:端口9300:Java程序访问的端口;端口9200:浏览器访问的端口
Elasticsearch 的版本需要跟后面的 Spring-Data-Elasticsearch 的版本相符,不然会不兼容(Spring 5.1.1 对应 Elasticsearch 6.8.0)
2.安装Head管理Elasticsearch插件
a.安装nodejs:在nodejs官网下载msi,地址:https://nodejs.org/en/download/,安装后在CMD命令行输入 node -v 查看是否安装成功
b.安装grunt:在CMD命令行输入 npm install -g grunt-cli 安装grunt,安装后输入 grunt -version 查看是否安装成功
c.下载Head:在GitHub下载并解压 elasticsearch-head-master,地址:https://github.com/mobz/elasticsearch-head
d.修改Head配置:修改Head根目录下Gruntfile.js,添加:hostname:‘*‘,
e.修改Elasticsearch配置:修改 Elasticsearch 的 config 目录下的 elasticsearch.yml 文件,添加如下配置。并重启
network.host: 127.0.0.1 # 解决elasticsearch-head 集群健康值: 未连接问题 http.cors.enabled: true http.cors.allow-origin: "*"
f.安装Head:在 elasticsearch-head-master 根目录下执行命令 npm install 进行安装
g.启动Head:同样在 elasticsearch-head-master 根目录下执行命令 grunt server(或者npm run start)
h.访问Head:在浏览器中访问 http://localhost:9100/ 即可进入管理界面
3.安装IK中文分词器
a.下载:在GitHub上下载对应版本的IK分词器zip包,地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
b.注意:Elasticsearch和IK分词器必须版本统一
c.解压安装:解压到 elasticsearch 的 plugins 目录下,并改名为 ik。并重启 elasticsearch
4.使用 Spring-Data-Elasticsearch 操作 Elasticsearch
a.导入pom依赖
<properties> ...... <!-- spring --> <spring.version>5.1.1.RELEASE</spring.version> </properties> <dependencies> <!-- elasticsearch --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.1.1.RELEASE</version> </dependency> <!-- spring-5.X --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- AOP-AspectJ spring-aop依赖 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.6</version> </dependency> <!-- jackson-json spring-mvc依赖 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.4</version> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies>
b.创建BaseEntity基础实体类
public class BaseEntity { @Id private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } }
c.创建Article和Author实体类
//index相当于数据库,type相当于表 @Document(indexName = "elasticsearch", type = "article") public class Article extends BaseEntity { private String title; private String content; //内嵌对象 @Field(type = FieldType.Nested) private List<Author> authors; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public List<Author> getAuthors() { return authors; } public void setAuthors(List<Author> authors) { this.authors = authors; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Article: id[" + this.getId() + "], title[" + title + "], content[" + content + "], authors[" + authors + "]"; } }
public class Author { private String name; private int year; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } @Override public String toString() { return "Author: name[" + name + "], year[" + year + "]"; } }
d.创建BaseDao基础DAO
public class BaseDao<T extends BaseEntity> { @Resource(name="elasticsearchTemplate") protected ElasticsearchTemplate esTemplate; protected Class<T> clazz; @PostConstruct private void construct(){ clazz = (Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } /** * 保存单个对象 * @param t 对象 * @return */ public boolean save(T t){ String id = t.getId(); if (id == null) { id = UUID.randomUUID().toString().replaceAll("-", ""); t.setId(id); } IndexQuery indexQuery = new IndexQueryBuilder().withId(id).withObject(t).build(); esTemplate.index(indexQuery); return true; } /** * 保存多个 * @param list 对象集合 * @return */ public boolean save(List<T> list){ List<IndexQuery> queries = new ArrayList<IndexQuery>(); for (T t : list) { String id = t.getId(); if (id == null) { id = UUID.randomUUID().toString().replaceAll("-", ""); t.setId(id); } IndexQuery indexQuery = new IndexQueryBuilder().withId(id).withObject(t).build(); queries.add(indexQuery); } esTemplate.bulkIndex(queries); return true; } /** * 根据ID删除 * @param id 对象ID * @return */ public boolean deleteById(String id){ esTemplate.delete(clazz, id); return true; } /** * 根据多个ID删除 * @param idList 对象ID集合 * @return */ public boolean deleteByIds(List<String> idList) { DeleteQuery deleteQuery = new DeleteQuery(); BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); if(idList != null) { for (String id : idList) { queryBuilder.should(QueryBuilders.matchQuery("id", id)); } } deleteQuery.setQuery(queryBuilder);; esTemplate.delete(deleteQuery, clazz); return true; } /** * 根据过滤条件删除 * @param filter 过滤条件Map * @return */ public boolean delete(Map<String,Object> filter){ DeleteQuery deleteQuery = new DeleteQuery(); BoolQueryBuilder queryBuilder = QueryBuilders. boolQuery(); if(filter != null) { for (Map.Entry<String, Object> entry : filter.entrySet()) { //"content.keyword" 表示不进行分词(精准查询),解决 "content" 分词后 term 查不到数据的问题 queryBuilder.must(QueryBuilders.matchQuery(entry.getKey() + ".keyword", entry.getValue())); } } deleteQuery.setQuery(queryBuilder); esTemplate.delete(deleteQuery, clazz); return true; } /** * 根据条件查询集合 * @param filter 过滤条件Map * @param highFields 高亮字段 * @param sortField 排序字段 * @param order 正序倒序 * @return */ public List<T> queryList(Map<String, Object> filter, final List<String> highFields, String sortField, SortOrder order) { NativeSearchQueryBuilder searchBuilder = new NativeSearchQueryBuilder(); //-----------------------------高亮----------------------------- List<Field> fieldList = new ArrayList<>(); if(highFields != null) { for (String highField : highFields) { fieldList.add(new HighlightBuilder.Field(highField).preTags("<em>").postTags("</em>").fragmentSize(250)); } } searchBuilder.withHighlightFields(fieldList.toArray(new Field[fieldList.size()])); //-----------------------------排序----------------------------- if (sortField != null && order != null){ searchBuilder.withSort(new FieldSortBuilder(sortField + ".keyword").order(order)); } //-----------------------------过滤条件----------------------------- BoolQueryBuilder queryBuilder= QueryBuilders.boolQuery(); for (Map.Entry<String, Object> entry : filter.entrySet()) { queryBuilder.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue())); } searchBuilder.withQuery(queryBuilder); //-----------------------------查询建立----------------------------- SearchQuery searchQuery = searchBuilder.build(); Page<T> page = null; //如果设置高亮 if (highFields != null && highFields.size() > 0) { page = esTemplate.queryForPage(searchQuery, clazz, new SearchResultMapper() { @Override public <T> AggregatedPage<T> mapResults(SearchResponse response,Class<T> clazz, Pageable pageable) { List<T> list = new ArrayList<T>(); for (SearchHit searchHit : response.getHits()) { if (response.getHits().getHits().length <= 0) { return null; } Map<String, Object> entityMap = searchHit.getSourceAsMap(); for (String highName : highFields) { String highValue = searchHit.getHighlightFields().get(highName).fragments()[0].toString(); entityMap.put(highName, highValue); } T t = JSONObject.parseObject(JSONObject.toJSONString(entityMap), clazz); list.add(t); } if (list.size() > 0) { return new AggregatedPageImpl<T>(list); } return null; } }); //如果不设置高亮 } else{ page = esTemplate.queryForPage(searchQuery, clazz); } return page.getContent(); } /** * 根据条件查询分页列表 * @param filter 过滤条件Map * @param highFields 高亮字段 * @param sortField 排序字段 * @param order 正序倒序 * @param pageIndex 当前页 * @param pageSize 分页大小 * @return */ public Map<String, Object> queryPage(Map<String,Object> filter, final List<String> highFields, String sortField, SortOrder order, int pageIndex, int pageSize) { NativeSearchQueryBuilder searchBuilder = new NativeSearchQueryBuilder(); //-----------------------------高亮----------------------------- List<Field> fieldList = new ArrayList<>(); if(highFields != null) { for (String highField : highFields) { fieldList.add(new HighlightBuilder.Field(highField).preTags("<em>").postTags("</em>").fragmentSize(250)); } } searchBuilder.withHighlightFields(fieldList.toArray(new Field[fieldList.size()])); //-----------------------------排序----------------------------- if (sortField != null && order != null){ searchBuilder.withSort(new FieldSortBuilder(sortField + ".keyword").order(order)); } //-----------------------------分页----------------------------- searchBuilder.withPageable(PageRequest.of(pageIndex, pageSize)); //-----------------------------过滤条件----------------------------- BoolQueryBuilder queryBuilder= QueryBuilders.boolQuery(); for (Map.Entry<String, Object> entry : filter.entrySet()) { queryBuilder.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue())); } searchBuilder.withQuery(queryBuilder); //-----------------------------查询建立----------------------------- SearchQuery searchQuery = searchBuilder.build(); Page<T> page = null; //如果设置高亮 if (highFields != null && highFields.size() > 0) { page = esTemplate.queryForPage(searchQuery, clazz, new SearchResultMapper() { @Override public <T> AggregatedPage<T> mapResults(SearchResponse response,Class<T> clazz, Pageable pageable) { List<T> list = new ArrayList<T>(); for (SearchHit searchHit : response.getHits()) { if (response.getHits().getHits().length <= 0) { return null; } Map<String, Object> entityMap = searchHit.getSourceAsMap(); for (String highName : highFields) { String highValue = searchHit.getHighlightFields().get(highName).fragments()[0].toString(); entityMap.put(highName, highValue); } T t = JSONObject.parseObject(JSONObject.toJSONString(entityMap), clazz); list.add(t); } if (list.size() > 0) { return new AggregatedPageImpl<T>(list); } return null; } }); //如果不设置高亮 } else{ page = esTemplate.queryForPage(searchQuery, clazz); } //-----------------------------查询数据总条数----------------------------- searchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder).build(); long totalCount = esTemplate.count(searchQuery, clazz); //组装结果 Map<String, Object> resultMap = new HashMap<>(); resultMap.put("pageIndex", pageIndex); resultMap.put("pageSize", pageSize); resultMap.put("data", page.getContent()); resultMap.put("totalCount", totalCount); return resultMap; } }
参考文档:https://blog.csdn.net/chen_2890/article/details/83757022
https://blog.csdn.net/lihuanlin93/article/details/83448967
原文地址:https://www.cnblogs.com/vettel0329/p/11096687.html