package com.example.xiaoshiweixinback.service.importPatent; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.InlineScript; import co.elastic.clients.elasticsearch._types.Script; import co.elastic.clients.elasticsearch._types.SortOptions; import co.elastic.clients.elasticsearch._types.SortOrder; import co.elastic.clients.elasticsearch._types.aggregations.*; import co.elastic.clients.elasticsearch._types.query_dsl.Query; import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.elasticsearch.core.SearchResponse; import co.elastic.clients.elasticsearch.core.search.FieldCollapse; import co.elastic.clients.elasticsearch.core.search.Hit; import co.elastic.clients.json.JsonData; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.example.xiaoshiweixinback.business.common.base.Records; import com.example.xiaoshiweixinback.business.exception.BusinessException; import com.example.xiaoshiweixinback.business.exception.ExceptionEnum; import com.example.xiaoshiweixinback.business.utils.BeanUtil; import com.example.xiaoshiweixinback.business.utils.CacheUtil; import com.example.xiaoshiweixinback.business.utils.LoginUtils; import com.example.xiaoshiweixinback.business.utils.ToolUtil; import com.example.xiaoshiweixinback.business.utils.parseQueryToTree.expressManager; import com.example.xiaoshiweixinback.business.utils.parseQueryToTree.operateNode; import com.example.xiaoshiweixinback.business.utils.parseQueryToTree.treeNode; import com.example.xiaoshiweixinback.domain.AssoPersonProduct; import com.example.xiaoshiweixinback.domain.es.*; import com.example.xiaoshiweixinback.entity.dto.esPicture.EsPictureNoDTO; import com.example.xiaoshiweixinback.entity.dto.patent.*; import com.example.xiaoshiweixinback.entity.patent.MapRequest; import com.example.xiaoshiweixinback.entity.patent.QueryRequest; import com.example.xiaoshiweixinback.entity.patent.StringRequest; import com.example.xiaoshiweixinback.entity.vo.PersonnelVO; import com.example.xiaoshiweixinback.entity.vo.esPicture.EsPatentVectorVo; import com.example.xiaoshiweixinback.entity.vo.esPicture.EsPictureNoVo; import com.example.xiaoshiweixinback.mapper.AssoPersonProductMapper; import com.example.xiaoshiweixinback.service.common.FileManagerService; import com.example.xiaoshiweixinback.service.common.GetVectorService; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.io.File; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @Service @RequiredArgsConstructor(onConstructor_ = {@Lazy}) public class EsPatentService { private final ElasticsearchClient client; @Autowired private EsService esService; @Autowired private CacheUtil cacheUtils; @Autowired private AssoPersonProductMapper assoPersonProductMapper; @Autowired private EsDenseVectorService esDenseVectorService; @Autowired private FileManagerService fileManagerService; @Autowired private GetVectorService getVectorService; @Autowired private FormatQueryService formatQueryService; @Value("${ES.patentVector}") private String patentVectorName; @Value("${ES.patent}") private String patentMapName; /** * 收藏专利 * * @param patentDTO * @return */ public boolean collectPatent(CollectPatentDTO patentDTO) throws IOException { boolean flag = false; List patentNos = patentDTO.getPatentNos(); Integer productId = patentDTO.getProductId(); //获取用户 PersonnelVO personnelVO = cacheUtils.getLoginUser(LoginUtils.getToken()); if (ToolUtil.isEmpty(personnelVO)) { throw new BusinessException(ExceptionEnum.THE_GET_INFORMATION_TOKEN_INVALID); } String uuid = personnelVO.getUuid(); //获取人员产品关联表id AssoPersonProduct assoPersonProduct = assoPersonProductMapper.selectOne(new LambdaQueryWrapper() .eq(AssoPersonProduct::getProductId, productId) .eq(AssoPersonProduct::getPersonUuid, uuid)); Integer assoPersonProductId = assoPersonProduct.getId(); //判断该专利是否已经被收藏 List patentNoList = this.selectPatentByProductId(assoPersonProductId); patentNos.removeAll(patentNoList); //根据专利号获取专利id List list = new ArrayList<>(); if (!CollectionUtils.isEmpty(patentNos)) { for (String patentNo : patentNos) { String patentId = this.selectPatentByPatentNo(patentNo); Patent patent = new Patent(); patent.setProductId(assoPersonProductId); PatentJoin patentJoin = new PatentJoin(); patentJoin.setParent(patentId); patentJoin.setName("product"); patent.setPatentJoin(patentJoin); try { String id = esService.addChildPatent(patent, patentId); list.add(id); } catch (Exception e) { } } } if (ToolUtil.equals(list.size(), patentNos.size())) { flag = true; } return flag; } /** * 查询收藏专利 * * @param dto * @return * @throws IOException */ public Records selectCollectPatent(SelectCollectPatentDTO dto) throws IOException { Integer assoPersonProductId = dto.getAssoPersonProductId(); Long pageNum = dto.getCurrent(); Long pageSize = dto.getSize(); List list = new ArrayList<>(); SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = QueryBuilders.term(i -> i.field("product_id").value(assoPersonProductId)); Query query = QueryBuilders.hasChild(i -> i.type("product").query(q)); builder.query(query); //分页 if (pageNum != null && pageSize != null && pageNum > 0 && pageSize > 0) { builder.from((pageNum.intValue() - 1) * pageSize.intValue()).size(pageSize.intValue()); } //解除最大条数限制 builder.trackTotalHits(i -> i.enabled(true)); SearchResponse response = client.search(builder.build(), Patent.class); List> hits = response.hits().hits(); long total = response.hits().total().value(); for (Hit hit : hits) { Patent patent = hit.source(); PatentColumnDTO columnDTO = this.getPatentColumnDTO(patent, null, null); list.add(columnDTO); } Records records = new Records(); records.setCurrent(pageNum); records.setSize(pageSize); records.setData(list); records.setTotal(total); return records; } /** * 删除收藏专利 * * @param patentDTO * @return * @throws IOException */ public boolean delCollectPatent(DelCollectPatentDTO patentDTO) throws IOException { Integer assoPersonProductId = patentDTO.getAssoPersonProductId(); List patentNos = patentDTO.getPatentNos(); List patentIds = new ArrayList<>(); for (String patentNo : patentNos) { List list = this.selectChildPatentId(patentNo, assoPersonProductId); patentIds.addAll(list); } if (!CollectionUtils.isEmpty(patentIds)) { Integer num = esService.deleteWxPatent(patentIds); if (num < 1) { throw new BusinessException(ExceptionEnum.THE_FAIL_TO_DELETE); } } else { return false; } return true; } //根据专利号、assoPersonProductId查询相关专利id public List selectChildPatentId(String patentNo, Integer assoPersonProductId) throws IOException { List list = new ArrayList<>(); SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = QueryBuilders.term(i -> i.field("product_id").value(assoPersonProductId)); Query query = QueryBuilders.term(i -> i.field("patent_no.keyword").value(patentNo)); Query q1 = QueryBuilders.hasParent(i -> i.parentType("patent").query(query)); Query bool = QueryBuilders.bool(i -> i.must(q, q1)); builder.query(bool); //解除最大条数限制 builder.trackTotalHits(i -> i.enabled(true)); SearchResponse response = client.search(builder.build(), Patent.class); List> hits = response.hits().hits(); for (Hit hit : hits) { String id = hit.id(); list.add(id); } return list; } //装载专利清单列表的数据 public PatentColumnDTO getPatentColumnDTO(Patent patent, Integer projectId, String id) { PatentColumnDTO columnDTO = new PatentColumnDTO(); BeanUtil.copy(patent, columnDTO); if (ToolUtil.isNotEmpty(patent.getApplicantAddr())) { PersonAddress applicantAddr = patent.getApplicantAddr(); columnDTO.setAppAddress(applicantAddr.getAddress()); columnDTO.setApplicantCountry(applicantAddr.getCountry()); columnDTO.setAppProvince(applicantAddr.getProvince()); columnDTO.setAppCity(applicantAddr.getCity()); columnDTO.setAppDistrict(applicantAddr.getDistrict()); } if (ToolUtil.isNotEmpty(patent.getRightHolderAddr())) { PersonAddress rightAddr = patent.getRightHolderAddr(); columnDTO.setRightAddress(rightAddr.getAddress()); columnDTO.setRightCountry(rightAddr.getCountry()); columnDTO.setRightProvince(rightAddr.getProvince()); columnDTO.setRightCity(rightAddr.getCity()); columnDTO.setRightDistrict(rightAddr.getDistrict()); } columnDTO.setApplicant(this.loadName(patent.getApplicant())); columnDTO.setRightHolder(this.loadName(patent.getRightHolder())); columnDTO.setInventor(this.loadName(patent.getInventor())); return columnDTO; } //通用返回申请人、权利人、发明人 public List loadName(List list) { List collect = new ArrayList<>(); if (!CollectionUtils.isEmpty(list)) { collect = list.stream().filter(i -> StringUtils.isNotEmpty(i.getName())).map(PatentPerson::getName).collect(Collectors.toList()); } return collect; } /** * 根据专利号获取专利id * * @param patentNo * @return * @throws IOException */ public String selectPatentByPatentNo(String patentNo) throws IOException { String id = ""; SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = QueryBuilders.term(i -> i.field("patent_no.keyword").value(patentNo)); builder.query(q); builder.size(10); SearchResponse response = client.search(builder.build(), Patent.class); List> hits = response.hits().hits(); for (Hit hit : hits) { id = hit.id(); } return id; } /** * 根据专利号获取专利id * * @param patentNo * @return * @throws IOException */ public PatentColumnDTO selectPatentInfoByPatentNo(String patentNo) throws IOException { PatentColumnDTO columnDTO = new PatentColumnDTO(); SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = QueryBuilders.term(i -> i.field("patent_no.keyword").value(patentNo)); builder.query(q); builder.size(10); SearchResponse response = client.search(builder.build(), Patent.class); List> hits = response.hits().hits(); for (Hit hit : hits) { Patent patent = hit.source(); columnDTO = this.getPatentColumnDTO(patent, null, null); } return columnDTO; } /** * 判断该专利是否已经被收藏 * * @param personProductId * @return * @throws IOException */ public List selectPatentByProductId(Integer personProductId) throws IOException { List list = new ArrayList<>(); SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = QueryBuilders.term(i -> i.field("product_id").value(personProductId)); Query query = QueryBuilders.hasChild(i -> i.type("product").query(q)); builder.query(query); builder.size(10); SearchResponse response = client.search(builder.build(), Patent.class); List> hits = response.hits().hits(); for (Hit hit : hits) { Patent patent = hit.source(); list.add(patent.getPatentNo()); } return list; } //-------------------查询相关专利信息----------- /** * 查询专利(用于导出专利数据) * * @param patentDTO * @param file * @return * @throws Exception */ public List selectPatent(SelectPatentDTO patentDTO, File file) throws Exception { List columnDTOS = new ArrayList<>(); if (!CollectionUtils.isEmpty(patentDTO.getAppNos())) { for (String appNo : patentDTO.getAppNos()) { //获取专利的多张摘要附图 EsPictureNoDTO esPictureNoDTO = new EsPictureNoDTO(); esPictureNoDTO.setAppNo(appNo); List noVos = esDenseVectorService.getPictureByNo(esPictureNoDTO); List guids = noVos.stream().map(EsPictureNoVo::getGuid).collect(Collectors.toList()); //根据专利申请号appNo获取专利信息 PatentColumnDTO columnDTO = this.selectPatentByAppNo(appNo); columnDTO.setPictureGuids(guids); columnDTOS.add(columnDTO); } } else { //根据条件获取图片专利里的数据信息,如appNo List vectorVos = this.selectPicturePatent(patentDTO, file); if (!CollectionUtils.isEmpty(vectorVos)) { for (EsPatentVectorVo vectorVo : vectorVos) { String appNo = vectorVo.getAppNo(); //获取专利的多张摘要附图 EsPictureNoDTO esPictureNoDTO = new EsPictureNoDTO(); esPictureNoDTO.setAppNo(appNo); List noVos = esDenseVectorService.getPictureByNo(esPictureNoDTO); List guids = noVos.stream().map(EsPictureNoVo::getGuid).collect(Collectors.toList()); //根据专利申请号appNo获取专利信息 PatentColumnDTO columnDTO = this.selectPatentByAppNo(appNo); columnDTO.setPictureGuids(guids); columnDTOS.add(columnDTO); } } } return columnDTOS; } /** * 获取图片专利里的信息 * * @param patentDTO * @param file * @return * @throws Exception */ public List selectPicturePatent(SelectPatentDTO patentDTO, File file) throws Exception { Boolean ifAllExport = patentDTO.getIfAllExport(); Integer limitNum = patentDTO.getLimitNum(); SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = null; String condition = esDenseVectorService.appendCondition(patentDTO.getProductId(), patentDTO.getKey(), patentDTO.getAppCountry(), patentDTO.getCompanyName()); if (StringUtils.isNotEmpty(condition)) { //1. 解析检索条件 treeNode tree = expressManager.getInstance().Parse(condition, false); //2. 从es中检索数据 q = formatQueryService.EsQueryToQuery((operateNode) tree, "patentVector", null); } //获取图片向量 List imageList = new ArrayList<>(); List stringList = new ArrayList<>(); if (file != null && file.exists() && file.length() != 0) { stringList = getVectorService.getVectorByFile(file); } else if (StringUtils.isNotEmpty(patentDTO.getDescription())) { stringList = getVectorService.getVectorByText(patentDTO.getDescription()); } stringList.forEach(item -> { Float a = Float.parseFloat(item); imageList.add(a); }); if (!CollectionUtils.isEmpty(imageList)) { String source = "cosineSimilarity(params.queryVector, 'my_vector') + 1.0"; InlineScript inlineScript = InlineScript.of(i -> i.lang("painless").params("queryVector", JsonData.of(imageList)).source(source)); Script script = Script.of(i -> i.inline(inlineScript)); Query query = null; if (q != null) { Query finalQ = q; query = QueryBuilders.scriptScore(i -> i.script(script) .query(finalQ)); } else { query = QueryBuilders.scriptScore(i -> i.script(script) .query(org.springframework.data.elasticsearch.client.elc.QueryBuilders.matchAllQueryAsQuery())); } builder.query(query); } else { builder.query(q); } //根据申请号去重 FieldCollapse collapse = FieldCollapse.of(i -> i.field("app_no")); builder.collapse(collapse); //分页 if (Boolean.TRUE.equals(ifAllExport)) { builder.from(0).size(999999); } else { builder.size(limitNum); } //解除最大条数限制 builder.trackTotalHits(i -> i.enabled(true)); SearchResponse response = client.search(builder.build(), PatentVector.class); List> hits = response.hits().hits(); List vectorVos = new ArrayList<>(); Double fixedScore = 1.7d; for (Hit hit : hits) { Double score = hit.score(); if (score > fixedScore) { PatentVector vector = hit.source(); EsPatentVectorVo vectorVo = new EsPatentVectorVo(); BeanUtil.copy(vector, vectorVo); vectorVos.add(vectorVo); } } return vectorVos; } /** * 根据申请号查询专利信息 * * @param appNo * @return * @throws IOException */ public PatentColumnDTO selectPatentByAppNo(String appNo) throws IOException { PatentColumnDTO columnDTO = new PatentColumnDTO(); SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index(patentMapName); Query q = QueryBuilders.term(i -> i.field("app_no.keyword").value(appNo)); builder.query(q); builder.size(10); SearchResponse response = client.search(builder.build(), Patent.class); List> hits = response.hits().hits(); for (Hit hit : hits) { Patent patent = hit.source(); columnDTO = this.getPatentColumnDTO(patent, null, null); } return columnDTO; } /** * Es检索 * * @param queryRequest 检索条件 * @return */ public PatentDTO esSearch(QueryRequest queryRequest) throws Exception { PatentDTO dto = new PatentDTO(); String searchCondition = ""; Integer projectId = queryRequest.getProjectId(); Long current = queryRequest.getCurrent(); Long size = queryRequest.getSize(); //判断表达式 if (queryRequest instanceof StringRequest) { searchCondition = ((StringRequest) queryRequest).getSearchQuery(); } else if (queryRequest instanceof MapRequest) { Map map = ((MapRequest) queryRequest).getSearchQuery(); StringBuilder stringBuilder = new StringBuilder(); for (String key : map.keySet()) { Object value = map.get(key); if (!"".contentEquals(stringBuilder)) { stringBuilder = stringBuilder.append(" AND ").append(key).append("=").append(value); } else { stringBuilder = stringBuilder.append(key).append("=").append(value); } } searchCondition = stringBuilder.toString(); } String condition = searchCondition; SearchRequest.Builder builder = new SearchRequest.Builder(); //设置查询索引 builder.index("wxpatent"); //1. 解析检索条件 treeNode tree = expressManager.getInstance().Parse(condition, false); //3. 从es中检索数据 Query q = formatQueryService.EsQueryToQuery((operateNode) tree, "patent", projectId); builder.query(q); //排序 // List optionsList = new ArrayList<>(); // // SortOptions sortOptions = SortOptions.of(i -> i.field(j -> j.field("public_date").order(SortOrder.Desc).missing(-1))); // optionsList.add(sortOptions); // // builder.sort(optionsList); // //分页 // if (current != null && size != null && current > 0 && size > 0) { // builder.from((current.intValue() - 1) * size.intValue()).size(size.intValue()); // } else { // builder.from(1).size(99999); // } //解除最大条数限制 builder.trackTotalHits(i -> i.enabled(true)); SearchResponse response = client.search(builder.build(), Patent.class); List list = new ArrayList<>(); long total = 0L; List> hits = response.hits().hits(); total = response.hits().total().value(); for (Hit hit : hits) { // String id = hit.id(); // Patent esMess = hit.source(); // PatentColumnDTO columnDTO = this.getPatentColumnDTO(esMess, projectId, id); // list.add(columnDTO); } dto.setTotal(total); dto.setPatents(list); dto.setPageNum(current); dto.setPageSize(size); return dto; } }