EsPatentService.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. package com.example.xiaoshiweixinback.service.importPatent;
  2. import co.elastic.clients.elasticsearch.ElasticsearchClient;
  3. import co.elastic.clients.elasticsearch._types.InlineScript;
  4. import co.elastic.clients.elasticsearch._types.Script;
  5. import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
  6. import co.elastic.clients.elasticsearch._types.aggregations.AggregationBuilders;
  7. import co.elastic.clients.elasticsearch._types.query_dsl.Query;
  8. import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
  9. import co.elastic.clients.elasticsearch.core.SearchRequest;
  10. import co.elastic.clients.elasticsearch.core.SearchResponse;
  11. import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
  12. import co.elastic.clients.elasticsearch.core.search.Hit;
  13. import co.elastic.clients.json.JsonData;
  14. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  15. import com.example.xiaoshiweixinback.business.common.base.Records;
  16. import com.example.xiaoshiweixinback.business.exception.BusinessException;
  17. import com.example.xiaoshiweixinback.business.exception.ExceptionEnum;
  18. import com.example.xiaoshiweixinback.business.utils.BeanUtil;
  19. import com.example.xiaoshiweixinback.business.utils.CacheUtil;
  20. import com.example.xiaoshiweixinback.business.utils.LoginUtils;
  21. import com.example.xiaoshiweixinback.business.utils.ToolUtil;
  22. import com.example.xiaoshiweixinback.business.utils.parseQueryToTree.expressManager;
  23. import com.example.xiaoshiweixinback.business.utils.parseQueryToTree.operateNode;
  24. import com.example.xiaoshiweixinback.business.utils.parseQueryToTree.treeNode;
  25. import com.example.xiaoshiweixinback.domain.AssoPersonProduct;
  26. import com.example.xiaoshiweixinback.domain.es.*;
  27. import com.example.xiaoshiweixinback.entity.dto.esPicture.EsPictureNoDTO;
  28. import com.example.xiaoshiweixinback.entity.dto.patent.*;
  29. import com.example.xiaoshiweixinback.entity.vo.PersonnelVO;
  30. import com.example.xiaoshiweixinback.entity.vo.esPicture.EsPatentVectorVo;
  31. import com.example.xiaoshiweixinback.entity.vo.esPicture.EsPictureNoVo;
  32. import com.example.xiaoshiweixinback.mapper.AssoPersonProductMapper;
  33. import com.example.xiaoshiweixinback.service.common.FileManagerService;
  34. import com.example.xiaoshiweixinback.service.common.GetVectorService;
  35. import lombok.RequiredArgsConstructor;
  36. import org.apache.commons.lang3.ObjectUtils;
  37. import org.apache.commons.lang3.StringUtils;
  38. import org.springframework.beans.BeanUtils;
  39. import org.springframework.beans.factory.annotation.Autowired;
  40. import org.springframework.context.annotation.Lazy;
  41. import org.springframework.stereotype.Service;
  42. import org.springframework.util.CollectionUtils;
  43. import java.io.File;
  44. import java.io.IOException;
  45. import java.util.ArrayList;
  46. import java.util.Collections;
  47. import java.util.List;
  48. import java.util.stream.Collectors;
  49. @Service
  50. @RequiredArgsConstructor(onConstructor_ = {@Lazy})
  51. public class EsPatentService {
  52. private final ElasticsearchClient client;
  53. @Autowired
  54. private EsService esService;
  55. @Autowired
  56. private CacheUtil cacheUtils;
  57. @Autowired
  58. private AssoPersonProductMapper assoPersonProductMapper;
  59. @Autowired
  60. private EsDenseVectorService esDenseVectorService;
  61. @Autowired
  62. private FileManagerService fileManagerService;
  63. @Autowired
  64. private GetVectorService getVectorService;
  65. @Autowired
  66. private FormatQueryService formatQueryService;
  67. /**
  68. * 收藏专利
  69. *
  70. * @param patentDTO
  71. * @return
  72. */
  73. public boolean collectPatent(CollectPatentDTO patentDTO) throws IOException {
  74. boolean flag = false;
  75. List<String> patentNos = patentDTO.getPatentNos();
  76. Integer productId = patentDTO.getProductId();
  77. //获取用户
  78. PersonnelVO personnelVO = cacheUtils.getLoginUser(LoginUtils.getToken());
  79. if (ToolUtil.isEmpty(personnelVO)) {
  80. throw new BusinessException(ExceptionEnum.THE_GET_INFORMATION_TOKEN_INVALID);
  81. }
  82. String uuid = personnelVO.getUuid();
  83. //获取人员产品关联表id
  84. AssoPersonProduct assoPersonProduct = assoPersonProductMapper.selectOne(new LambdaQueryWrapper<AssoPersonProduct>()
  85. .eq(AssoPersonProduct::getProductId, productId)
  86. .eq(AssoPersonProduct::getPersonUuid, uuid));
  87. Integer assoPersonProductId = assoPersonProduct.getId();
  88. //判断该专利是否已经被收藏
  89. List<String> patentNoList = this.selectPatentByProductId(assoPersonProductId);
  90. patentNos.removeAll(patentNoList);
  91. //根据专利号获取专利id
  92. List<String> list = new ArrayList<>();
  93. if (!CollectionUtils.isEmpty(patentNos)) {
  94. for (String patentNo : patentNos) {
  95. String patentId = this.selectPatentByPatentNo(patentNo);
  96. Patent patent = new Patent();
  97. patent.setProductId(assoPersonProductId);
  98. PatentJoin patentJoin = new PatentJoin();
  99. patentJoin.setParent(patentId);
  100. patentJoin.setName("product");
  101. patent.setPatentJoin(patentJoin);
  102. try {
  103. String id = esService.addChildPatent(patent, patentId);
  104. list.add(id);
  105. } catch (Exception e) {
  106. }
  107. }
  108. }
  109. if (ToolUtil.equals(list.size(), patentNos.size())) {
  110. flag = true;
  111. }
  112. return flag;
  113. }
  114. /**
  115. * 查询收藏专利
  116. *
  117. * @param dto
  118. * @return
  119. * @throws IOException
  120. */
  121. public Records selectCollectPatent(SelectCollectPatentDTO dto) throws IOException {
  122. Integer assoPersonProductId = dto.getAssoPersonProductId();
  123. Long pageNum = dto.getCurrent();
  124. Long pageSize = dto.getSize();
  125. List<PatentColumnDTO> list = new ArrayList<>();
  126. SearchRequest.Builder builder = new SearchRequest.Builder();
  127. //设置查询索引
  128. builder.index("wxpatent");
  129. Query q = QueryBuilders.term(i -> i.field("product_id").value(assoPersonProductId));
  130. Query query = QueryBuilders.hasChild(i -> i.type("product").query(q));
  131. builder.query(query);
  132. //分页
  133. if (pageNum != null && pageSize != null && pageNum > 0 && pageSize > 0) {
  134. builder.from((pageNum.intValue() - 1) * pageSize.intValue()).size(pageSize.intValue());
  135. }
  136. //解除最大条数限制
  137. builder.trackTotalHits(i -> i.enabled(true));
  138. SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
  139. List<Hit<Patent>> hits = response.hits().hits();
  140. long total = response.hits().total().value();
  141. for (Hit<Patent> hit : hits) {
  142. Patent patent = hit.source();
  143. PatentColumnDTO columnDTO = this.getPatentColumnDTO(patent, null, null);
  144. list.add(columnDTO);
  145. }
  146. Records records = new Records();
  147. records.setCurrent(pageNum);
  148. records.setSize(pageSize);
  149. records.setData(list);
  150. records.setTotal(total);
  151. return records;
  152. }
  153. /**
  154. * 删除收藏专利
  155. *
  156. * @param patentDTO
  157. * @return
  158. * @throws IOException
  159. */
  160. public boolean delCollectPatent(DelCollectPatentDTO patentDTO) throws IOException {
  161. Integer assoPersonProductId = patentDTO.getAssoPersonProductId();
  162. List<String> patentNos = patentDTO.getPatentNos();
  163. List<String> patentIds = new ArrayList<>();
  164. for (String patentNo : patentNos) {
  165. List<String> list = this.selectChildPatentId(patentNo, assoPersonProductId);
  166. patentIds.addAll(list);
  167. }
  168. if (!CollectionUtils.isEmpty(patentIds)) {
  169. Integer num = esService.deleteWxPatent(patentIds);
  170. if (num < 1) {
  171. throw new BusinessException(ExceptionEnum.THE_FAIL_TO_DELETE);
  172. }
  173. } else {
  174. return false;
  175. }
  176. return true;
  177. }
  178. //根据专利号、assoPersonProductId查询相关专利id
  179. public List<String> selectChildPatentId(String patentNo, Integer assoPersonProductId) throws IOException {
  180. List<String> list = new ArrayList<>();
  181. SearchRequest.Builder builder = new SearchRequest.Builder();
  182. //设置查询索引
  183. builder.index("wxpatent");
  184. Query q = QueryBuilders.term(i -> i.field("product_id").value(assoPersonProductId));
  185. Query query = QueryBuilders.term(i -> i.field("patent_no.keyword").value(patentNo));
  186. Query q1 = QueryBuilders.hasParent(i -> i.parentType("patent").query(query));
  187. Query bool = QueryBuilders.bool(i -> i.must(q, q1));
  188. builder.query(bool);
  189. //解除最大条数限制
  190. builder.trackTotalHits(i -> i.enabled(true));
  191. SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
  192. List<Hit<Patent>> hits = response.hits().hits();
  193. for (Hit<Patent> hit : hits) {
  194. String id = hit.id();
  195. list.add(id);
  196. }
  197. return list;
  198. }
  199. //装载专利清单列表的数据
  200. public PatentColumnDTO getPatentColumnDTO(Patent patent, Integer projectId, String id) {
  201. PatentColumnDTO columnDTO = new PatentColumnDTO();
  202. BeanUtil.copy(patent, columnDTO);
  203. if (ToolUtil.isNotEmpty(patent.getApplicantAddr())) {
  204. PersonAddress applicantAddr = patent.getApplicantAddr();
  205. columnDTO.setAppAddress(applicantAddr.getAddress());
  206. columnDTO.setApplicantCountry(applicantAddr.getCountry());
  207. columnDTO.setAppProvince(applicantAddr.getProvince());
  208. columnDTO.setAppCity(applicantAddr.getCity());
  209. columnDTO.setAppDistrict(applicantAddr.getDistrict());
  210. }
  211. if (ToolUtil.isNotEmpty(patent.getRightHolderAddr())) {
  212. PersonAddress rightAddr = patent.getRightHolderAddr();
  213. columnDTO.setRightAddress(rightAddr.getAddress());
  214. columnDTO.setRightCountry(rightAddr.getCountry());
  215. columnDTO.setRightProvince(rightAddr.getProvince());
  216. columnDTO.setRightCity(rightAddr.getCity());
  217. columnDTO.setRightDistrict(rightAddr.getDistrict());
  218. }
  219. columnDTO.setApplicant(this.loadName(patent.getApplicant()));
  220. columnDTO.setRightHolder(this.loadName(patent.getRightHolder()));
  221. columnDTO.setInventor(this.loadName(patent.getInventor()));
  222. return columnDTO;
  223. }
  224. //通用返回申请人、权利人、发明人
  225. public List<String> loadName(List<PatentPerson> list) {
  226. List<String> collect = new ArrayList<>();
  227. if (!CollectionUtils.isEmpty(list)) {
  228. collect = list.stream().filter(i -> StringUtils.isNotEmpty(i.getName())).map(PatentPerson::getName).collect(Collectors.toList());
  229. }
  230. return collect;
  231. }
  232. /**
  233. * 根据专利号获取专利id
  234. *
  235. * @param patentNo
  236. * @return
  237. * @throws IOException
  238. */
  239. public String selectPatentByPatentNo(String patentNo) throws IOException {
  240. String id = "";
  241. SearchRequest.Builder builder = new SearchRequest.Builder();
  242. //设置查询索引
  243. builder.index("wxpatent");
  244. Query q = QueryBuilders.term(i -> i.field("patent_no.keyword").value(patentNo));
  245. builder.query(q);
  246. builder.size(10);
  247. SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
  248. List<Hit<Patent>> hits = response.hits().hits();
  249. for (Hit<Patent> hit : hits) {
  250. id = hit.id();
  251. }
  252. return id;
  253. }
  254. /**
  255. * 判断该专利是否已经被收藏
  256. *
  257. * @param personProductId
  258. * @return
  259. * @throws IOException
  260. */
  261. public List<String> selectPatentByProductId(Integer personProductId) throws IOException {
  262. List<String> list = new ArrayList<>();
  263. SearchRequest.Builder builder = new SearchRequest.Builder();
  264. //设置查询索引
  265. builder.index("wxpatent");
  266. Query q = QueryBuilders.term(i -> i.field("product_id").value(personProductId));
  267. Query query = QueryBuilders.hasChild(i -> i.type("product").query(q));
  268. builder.query(query);
  269. builder.size(10);
  270. SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
  271. List<Hit<Patent>> hits = response.hits().hits();
  272. for (Hit<Patent> hit : hits) {
  273. Patent patent = hit.source();
  274. list.add(patent.getPatentNo());
  275. }
  276. return list;
  277. }
  278. //-------------------查询相关专利信息-----------
  279. /**
  280. * 查询专利(用于导出专利数据)
  281. * @param patentDTO
  282. * @param file
  283. * @return
  284. * @throws Exception
  285. */
  286. public List<PatentColumnDTO> selectPatent(SelectPatentDTO patentDTO, File file) throws Exception {
  287. List<PatentColumnDTO> columnDTOS = new ArrayList<>();
  288. if (!CollectionUtils.isEmpty(patentDTO.getAppNos())) {
  289. for (String appNo : patentDTO.getAppNos()) {
  290. //获取专利的多张摘要附图
  291. EsPictureNoDTO esPictureNoDTO = new EsPictureNoDTO();
  292. esPictureNoDTO.setAppNo(appNo);
  293. List<EsPictureNoVo> noVos = esDenseVectorService.getPictureByNo(esPictureNoDTO);
  294. List<String> guids = noVos.stream().map(EsPictureNoVo::getGuid).collect(Collectors.toList());
  295. //根据专利申请号appNo获取专利信息
  296. PatentColumnDTO columnDTO = this.selectPatentByAppNo(appNo);
  297. columnDTO.setPictureGuids(guids);
  298. columnDTOS.add(columnDTO);
  299. }
  300. } else {
  301. //根据条件获取图片专利里的数据信息,如appNo
  302. List<EsPatentVectorVo> vectorVos = this.selectPicturePatent(patentDTO, file);
  303. if (!CollectionUtils.isEmpty(vectorVos)) {
  304. for (EsPatentVectorVo vectorVo : vectorVos) {
  305. String appNo = vectorVo.getAppNo();
  306. //获取专利的多张摘要附图
  307. EsPictureNoDTO esPictureNoDTO = new EsPictureNoDTO();
  308. esPictureNoDTO.setAppNo(appNo);
  309. List<EsPictureNoVo> noVos = esDenseVectorService.getPictureByNo(esPictureNoDTO);
  310. List<String> guids = noVos.stream().map(EsPictureNoVo::getGuid).collect(Collectors.toList());
  311. //根据专利申请号appNo获取专利信息
  312. PatentColumnDTO columnDTO = this.selectPatentByAppNo(appNo);
  313. columnDTO.setPictureGuids(guids);
  314. columnDTOS.add(columnDTO);
  315. }
  316. }
  317. }
  318. return columnDTOS;
  319. }
  320. /**
  321. * 获取图片专利里的信息
  322. * @param patentDTO
  323. * @param file
  324. * @return
  325. * @throws Exception
  326. */
  327. public List<EsPatentVectorVo> selectPicturePatent(SelectPatentDTO patentDTO, File file) throws Exception {
  328. Boolean ifAllExport = patentDTO.getIfAllExport();
  329. Integer limitNum = patentDTO.getLimitNum();
  330. SearchRequest.Builder builder = new SearchRequest.Builder();
  331. //设置查询索引
  332. builder.index("patent_vector");
  333. Query q = null;
  334. String condition = esDenseVectorService.appendCondition(patentDTO.getProductId(), patentDTO.getKey(), patentDTO.getAppCountry(), patentDTO.getName());
  335. if (StringUtils.isNotEmpty(condition)) {
  336. //1. 解析检索条件
  337. treeNode tree = expressManager.getInstance().Parse(condition, false);
  338. //2. 从es中检索数据
  339. q = formatQueryService.EsQueryToQuery((operateNode) tree, "patentVector", null);
  340. }
  341. //获取图片向量
  342. List<Float> imageList = new ArrayList<>();
  343. List<String> stringList = new ArrayList<>();
  344. if (file != null && file.exists() && file.length() != 0) {
  345. stringList = getVectorService.getVectorByFile(file);
  346. } else if (StringUtils.isNotEmpty(patentDTO.getDescription())) {
  347. stringList = getVectorService.getVectorByText(patentDTO.getDescription());
  348. }
  349. stringList.forEach(item -> {
  350. Float a = Float.parseFloat(item);
  351. imageList.add(a);
  352. });
  353. if (!CollectionUtils.isEmpty(imageList)) {
  354. String source = "cosineSimilarity(params.queryVector, 'my_vector') + 1.0";
  355. InlineScript inlineScript = InlineScript.of(i -> i.lang("painless").params("queryVector", JsonData.of(imageList)).source(source));
  356. Script script = Script.of(i -> i.inline(inlineScript));
  357. Query query = null;
  358. if (q != null) {
  359. Query finalQ = q;
  360. query = QueryBuilders.scriptScore(i -> i.script(script)
  361. .query(finalQ));
  362. } else {
  363. query = QueryBuilders.scriptScore(i -> i.script(script)
  364. .query(org.springframework.data.elasticsearch.client.elc.QueryBuilders.matchAllQueryAsQuery()));
  365. }
  366. builder.query(query);
  367. } else {
  368. builder.query(q);
  369. }
  370. //根据申请号去重
  371. FieldCollapse collapse = FieldCollapse.of(i -> i.field("app_no"));
  372. builder.collapse(collapse);
  373. //分页
  374. if (Boolean.TRUE.equals(ifAllExport)) {
  375. builder.from(0).size(999999);
  376. } else {
  377. builder.size(limitNum);
  378. }
  379. //解除最大条数限制
  380. builder.trackTotalHits(i -> i.enabled(true));
  381. SearchResponse<PatentVector> response = client.search(builder.build(), PatentVector.class);
  382. List<Hit<PatentVector>> hits = response.hits().hits();
  383. List<EsPatentVectorVo> vectorVos = new ArrayList<>();
  384. Double fixedScore = 1.7d;
  385. for (Hit<PatentVector> hit : hits) {
  386. Double score = hit.score();
  387. if (score > fixedScore) {
  388. PatentVector vector = hit.source();
  389. EsPatentVectorVo vectorVo = new EsPatentVectorVo();
  390. BeanUtil.copy(vector, vectorVo);
  391. vectorVos.add(vectorVo);
  392. }
  393. }
  394. return vectorVos;
  395. }
  396. /**
  397. * 根据申请号查询专利信息
  398. * @param appNo
  399. * @return
  400. * @throws IOException
  401. */
  402. public PatentColumnDTO selectPatentByAppNo(String appNo) throws IOException {
  403. PatentColumnDTO columnDTO = new PatentColumnDTO();
  404. SearchRequest.Builder builder = new SearchRequest.Builder();
  405. //设置查询索引
  406. builder.index("wxpatent");
  407. Query q = QueryBuilders.term(i -> i.field("patent_no.keyword").value(appNo));
  408. builder.query(q);
  409. builder.size(10);
  410. SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
  411. List<Hit<Patent>> hits = response.hits().hits();
  412. for (Hit<Patent> hit : hits) {
  413. Patent patent = hit.source();
  414. columnDTO = this.getPatentColumnDTO(patent, null, null);
  415. }
  416. return columnDTO;
  417. }
  418. }