package org.springblade.es.service; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.logging.log4j.util.Strings; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.reindex.*; import org.elasticsearch.script.ScriptType; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.springblade.common.cache.SysCache; import org.springblade.common.constant.EsTableConstant; import org.springblade.common.param.CommonParamSet; import org.springblade.common.utils.SpringUtils; import org.springblade.es.vo.EsParam; import org.springblade.modules.article.entity.Article; import org.springblade.modules.article.service.ArticleService; import org.springblade.modules.doorplateAddress.entity.DoorplateAddressEntity; import org.springblade.modules.doorplateAddress.service.IDoorplateAddressService; import org.springblade.modules.grid.service.IGridRangeService; import org.springblade.modules.house.entity.HouseEntity; import org.springblade.modules.house.entity.HouseholdEntity; import org.springblade.modules.house.service.IHouseService; import org.springblade.modules.house.service.IHouseholdService; import org.springblade.modules.house.vo.HouseVO; import org.springblade.modules.house.vo.HouseholdVO; import org.springblade.modules.place.entity.PlaceEntity; import org.springblade.modules.place.service.IPlaceService; import org.springblade.modules.place.vo.PlaceVO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.elasticsearch.script.Script; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Service public class ElasticsearchDocumentService { @Autowired private RestHighLevelClient client; @Autowired private ArticleService articleService; @Autowired private IPlaceService placeService; @Autowired private IHouseService houseService; @Autowired private IHouseholdService householdService; @Autowired private IGridRangeService gridRangeService; @Autowired private IDoorplateAddressService doorplateAddressService; @Value("${elasticsearch.sync}") private boolean elasticsearchSync; @Value("${elasticsearch.indexName}") private String indexName; /** * 检查索引是否已存在 * * @param indexName * @return */ public boolean isIndexExists(String indexName) { // 检查索引是否已存在 GetIndexRequest request = new GetIndexRequest(indexName); try { return client.indices().exists(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return false; } /** * 初始化数据 * * @param esParam * @return */ public boolean init(EsParam esParam) { if (!Strings.isBlank(esParam.getTableName())) { if (esParam.getTableName().equals("jczz_place")) { // 场所 initPlace(esParam); } if (esParam.getTableName().equals("jczz_article")) { // 通知文章 initArticle(esParam); } if (esParam.getTableName().equals("jczz_house")) { // 房屋 initHouse(esParam); } if (esParam.getTableName().equals("jczz_household")) { // 住户 initHousehold(esParam); } } // 返回 return true; } /** * 初始化数据 * * @param esParam * @return */ public boolean initPlace(EsParam esParam) { // 查询 int total = placeService.getAllListTotal(); int size = 1000; int num = total / size; for (int i = 1; i <= num + 1; i++) { List placeVOList = placeService.getAllList((i - 1) * size, size); // 遍历 if (placeVOList.size() > 0) { // 创建批量请求对象 BulkRequest bulkRequest = new BulkRequest(); for (PlaceVO place : placeVOList) { // 入es库 // 初始化Elasticsearch客户端 IndexRequest indexRequest = new IndexRequest(esParam.getIndexName()); // 不设置id // indexRequest.id("1"); indexRequest.source( "tableId", place.getId().toString(), "tableName", "jczz_place", "title", place.getPlaceName(), "name", place.getPrincipal(), "phone", place.getPrincipalPhone(), "idCard", place.getPrincipalIdCard(), "content", place.getLocation(), "communityCode", place.getCommunityCode() ); // 加入集合 bulkRequest.add(indexRequest); } BulkResponse bulkResponse = null; try { // 执行批量插入 bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 刷新索引,确保文档可搜索 client.indices().refresh(new RefreshRequest(esParam.getIndexName()), RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } System.out.println("批量插入结果: " + !bulkResponse.hasFailures()); } } // 返回 return true; } /** * 初始化公告数据 * * @param esParam * @return */ public boolean initArticle(EsParam esParam) { // 查询 int total = articleService.getAllListTotal(); int size = 10; int num = total / size; for (int i = 1; i <= num + 1; i++) { // 查询 List
articleList = articleService.getAllList((i - 1) * size, size); // 遍历 if (articleList.size() > 0) { BulkRequest bulkRequest = new BulkRequest(); for (Article article : articleList) { // 初始化Elasticsearch客户端 IndexRequest indexRequest = new IndexRequest(esParam.getIndexName()); String communityNameListString = SysCache.getAllCommunityNameListString(article.getArticleRange(),article.getId().toString()); Map map = new HashMap<>(1); map.put("communityCode",communityNameListString); String toString = new JSONObject(map).toString(); // 不设置id // indexRequest.id("1"); indexRequest.source("tableId", article.getId().toString(), "tableName", "jczz_article", "title", article.getTitle(), "communityCode", toString, "type", null != article.getType() ? article.getType().toString() : "", "content", article.getContent(), "articleType", article.getArticleType()); // 加入集合 bulkRequest.add(indexRequest); } BulkResponse bulkResponse = null; try { // 执行批量插入 bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 刷新索引,确保文档可搜索 client.indices().refresh(new RefreshRequest(esParam.getIndexName()), RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } System.out.println("批量插入结果: " + !bulkResponse.hasFailures()); } } // 返回 return true; } /** * 初始化住户数据 * * @param esParam * @return */ public boolean initHousehold(EsParam esParam) { // 查询 int total = householdService.getAllListTotal(); int size = 1000; int num = total / size; for (int i = 1; i <= num + 1; i++) { // 查询 List householdVOList = householdService.getAllList((i - 1) * size, size); // 遍历 if (householdVOList.size() > 0) { BulkRequest bulkRequest = new BulkRequest(); for (HouseholdVO household : householdVOList) { // 初始化Elasticsearch客户端 IndexRequest indexRequest = new IndexRequest(esParam.getIndexName()); // 不设置id // indexRequest.id("1"); indexRequest.source( "tableId", household.getId().toString(), "tableName", "jczz_household", "title", household.getName(), "relationship", household.getRelationship(), "name", household.getName(), "phone", household.getPhoneNumber(), "idCard", household.getIdCard(), "content", household.getAddress(), "communityCode", household.getCommunityCode() ); // 加入集合 bulkRequest.add(indexRequest); } BulkResponse bulkResponse = null; try { // 执行批量插入 bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 刷新索引,确保文档可搜索 client.indices().refresh(new RefreshRequest(esParam.getIndexName()), RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } System.out.println("批量插入结果: " + !bulkResponse.hasFailures()); } } // 返回 return true; } /** * 初始化房屋数据 * * @param esParam * @return */ public boolean initHouse(EsParam esParam) { // 查询 int total = houseService.getAllListTotal(); int size = 1000; int num = total / size; for (int i = 1; i <= num + 1; i++) { // 查询 List houseVOList = houseService.getAllList((i - 1) * size, size); // 遍历 if (houseVOList.size() > 0) { BulkRequest bulkRequest = new BulkRequest(); for (HouseVO house : houseVOList) { // 初始化Elasticsearch客户端 IndexRequest indexRequest = new IndexRequest(esParam.getIndexName()); // 不设置id // indexRequest.id("1"); indexRequest.source( "tableId", house.getId().toString(), "tableName", "jczz_house", "title", house.getHouseName(), "name", null, "phone", null, "idCard", null, "content", null, "communityCode", house.getCommunityCode() ); // 加入集合 bulkRequest.add(indexRequest); } BulkResponse bulkResponse = null; try { // 执行批量插入 bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 刷新索引,确保文档可搜索 client.indices().refresh(new RefreshRequest(esParam.getIndexName()), RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } System.out.println("批量插入结果: " + !bulkResponse.hasFailures()); } } // 返回 return true; } /** * 新增公告同步 * * @param esParam * @param article */ @Async public void addArticle(EsParam esParam, Article article) { if (elasticsearchSync) { // 查询当前文章范围对应的社区名称字符串集合 String communityNameListString = SysCache.getAllCommunityNameListString(article.getArticleRange(),article.getId().toString()); Map map = new HashMap<>(1); map.put("communityCode",communityNameListString); String toString = new JSONObject(map).toString(); try { indexDocument(esParam.getIndexName(), "tableId", article.getId().toString(), "tableName", "jczz_article", "title", article.getTitle(), "communityCode", toString, "type", null != article.getType() ? article.getType().toString() : "", "content", article.getContent(), "articleType", article.getArticleType() ); } catch (IOException e) { e.printStackTrace(); } } } /** * 新增场所同步 * * @param esParam * @param place */ @Async public void addPlace(EsParam esParam, PlaceEntity place) { if (elasticsearchSync) { try { indexDocument(esParam.getIndexName(), "tableId", place.getId().toString(), "tableName", "jczz_place", "title", place.getPlaceName(), "name", place.getPrincipal(), "phone", place.getPrincipalPhone(), "idCard", place.getPrincipalIdCard(), "content", place.getLocation(), "communityCode", placeService.getCommunityCode(place.getId()) ); } catch (IOException e) { e.printStackTrace(); } } } /** * 新增房屋同步 * * @param esParam * @param house */ @Async public void addHouse(EsParam esParam, HouseEntity house) { if (elasticsearchSync) { try { indexDocument(esParam.getIndexName(), "tableId", house.getId().toString(), "tableName", "jczz_house", "title", house.getHouseName(), "name", null, "phone", null, "idCard", null, "content", null, "communityCode", houseService.getCommunityCode(house.getId()) ); } catch (IOException e) { e.printStackTrace(); } } } /** * 新增住户同步 * * @param esParam * @param household */ @Async public void addHousehold(EsParam esParam, HouseholdEntity household) { if (elasticsearchSync) { try { indexDocument(esParam.getIndexName(), "tableId", household.getId().toString(), "tableName", "jczz_household", "title", household.getName(), "name", household.getName(), "phone", household.getPhoneNumber(), "idCard", household.getIdCard(), "relationship", household.getRelationship().toString(), "content", getAddress(household), "communityCode", householdService.getCommunityCode(household.getId()) ); } catch (IOException e) { e.printStackTrace(); } } } /** * 获取房屋地址 * @param household * @return */ public String getAddress(HouseholdEntity household) { if (!Strings.isBlank(household.getHouseCode())){ // 查询对应的房屋地址 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("address_code",household.getHouseCode()); List list = doorplateAddressService.list(queryWrapper); if (list.size()>0){ return list.get(0).getAddressName(); } // 房屋查不到的情况 if (!Strings.isBlank(household.getCurrentAddress())){ return household.getCurrentAddress(); } }else { return household.getCurrentAddress(); } return null; } /** * 插入数据到es * * @param index * @param values * @throws IOException */ public void indexDocument(String index, String... values) throws IOException { // 初始化Elasticsearch客户端 IndexRequest indexRequest = new IndexRequest(index); // 不设置id // indexRequest.id("1"); indexRequest.source(values); IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT); // 刷新索引,确保文档可搜索 client.indices().refresh(new RefreshRequest(index), RequestOptions.DEFAULT); System.out.println("Indexed document with id: " + indexResponse.getId()); } /** * 查询数据 * * @param page * @param esParam * @return */ public Object selectDocumentPage(IPage page, EsParam esParam) { if (Strings.isBlank(esParam.getIndexName())){ esParam.setIndexName(indexName); } // 判断索引是否存在 if (isIndexExists(esParam.getIndexName())) { // 全文搜索 SearchRequest searchRequest = new SearchRequest(esParam.getIndexName()); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); // searchSourceBuilder.query(QueryBuilders.multiMatchQuery(esParam.getSearchKey(), // "content", // "name", // "title", // "location", // "phone", // "idCard", // "communityCode") // .type(MultiMatchQueryBuilder.Type.BEST_FIELDS) // ); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); // boolQueryBuilder.should(QueryBuilders.matchQuery("content", esParam.getSearchKey())); // boolQueryBuilder.should(QueryBuilders.matchQuery("name", esParam.getSearchKey())); boolQueryBuilder.should(QueryBuilders.matchPhraseQuery("title", esParam.getSearchKey())); // boolQueryBuilder.should(QueryBuilders.matchQuery("location", esParam.getSearchKey())); // boolQueryBuilder.should(QueryBuilders.matchQuery("phone", esParam.getSearchKey())); // boolQueryBuilder.should(QueryBuilders.matchQuery("idCard", esParam.getSearchKey())); if (!Strings.isBlank(esParam.getTableName())) { boolQueryBuilder.must(QueryBuilders.matchQuery("tableName", esParam.getTableName())); } String roleName = SpringUtils.getRequestParam("roleName"); String communityCode = SpringUtils.getRequestParam("communityCode"); if (!Strings.isBlank(communityCode)) { if (!Strings.isBlank(roleName) && roleName.equals("inhabitant") && !Strings.isBlank(esParam.getHouseCode())){ // 居民根据房屋对应的小区过滤 boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("communityCode",gridRangeService.getDistrictIdByHouseCode(esParam.getHouseCode()))); }else { // 设置查询社区名称,编号有多个,数字类型目前无法匹配到 boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("communityCode", communityCode)); } } if (!Strings.isBlank(roleName)){ if (roleName.equals("wgy") || roleName.equals("mj")){ // 不查公告 boolQueryBuilder.mustNot(QueryBuilders.matchQuery("tableName", "jczz_article")); } if (roleName.equals("inhabitant")){ // 只查公告 boolQueryBuilder.must(QueryBuilders.matchQuery("tableName", "jczz_article")); } if (roleName.equals("wzcj")){ // 只查场所 boolQueryBuilder.must(QueryBuilders.matchQuery("tableName", "jczz_place")); } } boolQueryBuilder.minimumShouldMatch(1); searchSourceBuilder.query(boolQueryBuilder); int current = (int) page.getCurrent(); int size = (int) page.getSize(); //设置分页 searchSourceBuilder.size(size); searchSourceBuilder.from((current - 1) * size); //将搜索资源对象设置到搜索客户端中 searchRequest.source(searchSourceBuilder); //查询 SearchResponse searchResponse = null; try { searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } //解析搜索返回值 SearchHits searchHits = searchResponse.getHits(); //查询的总数 long count = searchHits.getTotalHits().value; List list = new ArrayList<>(); for (SearchHit hit : searchHits) { // System.out.println("hit.getId() = " + hit.getId()); Map result = hit.getSourceAsMap(); if (null != result){ if (result.get("tableName").toString().equals("jczz_article")){ result.put("typeName","通知公告"); } if (result.get("tableName").toString().equals("jczz_place")){ result.put("typeName","经营场所"); } if (result.get("tableName").toString().equals("jczz_house")){ result.put("typeName","房屋"); } if (result.get("tableName").toString().equals("jczz_household")){ result.put("typeName","住户"); } } // 文档源数据 // String source = hit.getSourceAsString(); list.add(result); } page.setRecords(list); page.setTotal(count); } return page; } /** * 根据索引删除 */ public boolean removeBatchByIndexNames(List indexNames) { for (String indexName : indexNames) { // 索引存在才删除 if (isIndexExists(indexName)) { DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName); try { // 执行删除索引操作 AcknowledgedResponse deleteResponse = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT); // 输出操作结果 boolean acknowledged = deleteResponse.isAcknowledged(); System.out.println("索引删除成功: " + acknowledged); } catch (IOException e) { e.printStackTrace(); } } } return true; } /** * 新增数据--有问题,待调整 */ @Async public boolean add(EsParam esParam, T item) { String str = "tableName," + esParam.getTableName() + ","; CommonParamSet commonParamSet = new CommonParamSet().setFieldValue(item.getClass(), item, EsTableConstant.articleList, str); try { indexDocument(esParam.getIndexName(), str); } catch (IOException e) { e.printStackTrace(); } return true; } /** * 修改数据 */ @Async public void update(EsParam esParam, T item,List columnList) { // 判断索引是否存在 if (elasticsearchSync && isIndexExists(esParam.getIndexName())) { // 创建更新请求 UpdateByQueryRequest updateRequest = new UpdateByQueryRequest(esParam.getIndexName()); // 设置查询条件,例如:更新所有字段text包含"old text"的文档 updateRequest.setQuery( QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("tableId", esParam.getTableId())) .must(QueryBuilders.matchQuery("tableName", esParam.getTableName())) ); Map data = new HashMap(); data.put("tableName", esParam.getTableName()); if (esParam.getTableName().equals("jczz_article")) { setArticleMap((Article) item, data); } if (esParam.getTableName().equals("jczz_place")) { setPlaceMap((PlaceEntity) item, data); } if (esParam.getTableName().equals("jczz_house")) { setHouseMap((HouseEntity) item, data); } if (esParam.getTableName().equals("jczz_household")) { setHouseholdMap((HouseholdEntity) item, data); } Map param = new HashMap(); param.put("data", data); // script will read data param value and assign to document source String source = "ctx._source=params.data"; Script script = new Script(ScriptType.INLINE, "painless", source, param); updateRequest.setScript(script); // 执行更新操作 try { client.updateByQuery(updateRequest, RequestOptions.DEFAULT); // 刷新索引,确保文档可搜索 client.indices().refresh(new RefreshRequest(esParam.getIndexName()), RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } } } /** * 设置公告map * @param item * @param data */ private void setArticleMap(Article item, Map data) { // 查询当前文章范围对应的社区名称字符串集合 String communityNameListString = SysCache.getAllCommunityNameListString(item.getArticleRange(),item.getId().toString()); Map map = new HashMap<>(1); map.put("communityCode",communityNameListString); String toString = new JSONObject(map).toString(); data.put("tableId",item.getId()); data.put("title",item.getTitle()); data.put("type",item.getType()); data.put("content",item.getContent()); data.put("articleType",item.getArticleType()); data.put("communityCode",toString); } /** * 设置场所map * @param item * @param data */ private void setPlaceMap(PlaceEntity item, Map data) { data.put("communityCode",placeService.getCommunityCode(item.getId())); data.put("tableId",item.getId()); data.put("title",item.getPlaceName()); data.put("name",item.getPrincipal()); data.put("phone",item.getPrincipalPhone()); data.put("idCard",item.getPrincipalIdCard()); data.put("content",item.getLocation()); } /** * 设置房屋map * @param item * @param data */ private void setHouseMap(HouseEntity item, Map data) { data.put("communityCode",houseService.getCommunityCode(item.getId())); data.put("tableId",item.getId()); data.put("title",item.getHouseName()); } /** * 设置住户map * @param item * @param data */ private void setHouseholdMap(HouseholdEntity item, Map data) { data.put("communityCode",householdService.getCommunityCode(item.getId())); data.put("tableId",item.getId()); data.put("title",item.getName()); data.put("relationship",item.getRelationship()); data.put("name",item.getName()); data.put("phone",item.getPhoneNumber()); data.put("idCard",item.getIdCard()); data.put("content",getAddress(item)); } /** * 删除数据--根据条件 */ public boolean removeByQuery(EsParam esParam) { if (elasticsearchSync && isIndexExists(esParam.getIndexName())) { DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(esParam.getIndexName()); // 根据多个条件 生成 boolQueryBuilder BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); if (!Strings.isBlank(esParam.getTableId())){ boolQueryBuilder .must(QueryBuilders.matchQuery("tableId", esParam.getTableId())); } if (!Strings.isBlank(esParam.getTableName())) { boolQueryBuilder .must(QueryBuilders.matchQuery("tableName", esParam.getTableName())); } deleteByQueryRequest.setQuery(boolQueryBuilder); try { BulkByScrollResponse bulkResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } } return true; } }