当前位置:   article > 正文

基于spring boot架构和word分词器的分词检索,排序,分页实现_java word分词器maven

java word分词器maven

       本文不适合Java初学者,适合对spring boot有一定了解的同学。 文中可能涉及到一些实体类、dao类、工具类文中没有这些类大家不必在意,不影响本文的核心内容,本文重在对方法的梳理。

    word分词器maven依赖

  1. <dependency>
  2. <groupId>org.apdplat</groupId>
  3. <artifactId>word</artifactId>
  4. <version>1.3</version>
  5. </dependency>
       spring boot的常见依赖在这里我就不列举了可以见文章 基于maven的spring boot 项目porm文件配置(含定时器,数据抓取,分词器依赖配置)

       先构建一个PageUtil类用于封装分页排序方法。

  1. package com.frank.demo.util;
  2. import java.text.ParseException;
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import java.util.List;
  6. public class PageUtil {
  7. // 分页方法
  8. public static <T> List<T> splitList(List<T> list, int pageSize, int curPage) {
  9. List<T> subList = new ArrayList<T>();
  10. int listSize = list.size();
  11. int star = pageSize * curPage;
  12. int end = pageSize * (curPage + 1);
  13. if (end > listSize) {
  14. end = listSize;
  15. }
  16. if (star >= listSize) {
  17. return new ArrayList<T>();
  18. }
  19. for (int i = star; i < end; i++) {
  20. subList.add(list.get(i));
  21. }
  22. return subList;
  23. }
  24. // 排序(搜索内容按照相似度高低排序)
  25. private static void comparator(List<EtlSearchCompanyResponseDto> data) {
  26. Collections.sort(data, new Comparator<EtlSearchCompanyResponseDto>() {
  27. @Overridepublic
  28. int compare(EtlSearchCompanyResponseDto o1, EtlSearchCompanyResponseDto o2) {
  29. int cp = 0;
  30. if (o1.getMatching() > o2.getMatching()) {
  31. cp = -1;
  32. } else if (o1.getMatching() < o2.getMatching()) {
  33. cp = 1;
  34. }
  35. return cp;
  36. }
  37. });
  38. }
  39. }
现在构建一个SearchService请看下面代码,

  1. package com.frank.demo.service;
  2. //java内部工具
  3. import java.util.Collections;
  4. import java.util.Comparator;
  5. import java.util.LinkedHashMap;
  6. import java.util.LinkedList;
  7. import java.util.List;
  8. import java.util.Map;
  9. //基于spring boot集成hibernate的标准查询
  10. import javax.persistence.criteria.CriteriaBuilder;
  11. import javax.persistence.criteria.CriteriaQuery;
  12. import javax.persistence.criteria.Predicate;
  13. import javax.persistence.criteria.Root;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.data.domain.Sort;
  16. import org.springframework.data.domain.Sort.Direction;
  17. import org.springframework.data.jpa.domain.Specification;
  18. import org.springframework.stereotype.Service;
  19. // 分词器
  20. import org.apdplat.word.WordSegmenter;
  21. import org.apdplat.word.segmentation.Word;
  22. //用到的dao、实体类、工具类等,本文重在方法上的理解不必在意这些辅助类
  23. import com.frank.demo.dao.EtlDataT1004Dao;
  24. import com.frank.demo.dao.EtlDataT1009Dao;
  25. import com.frank.demo.dao.EtlDataT1022Dao;
  26. import com.frank.demo.dto.EtlCreatDueDiligenceRequestDto;
  27. import com.frank.demo.dto.EtlSearchCompanyResponseDto;
  28. import com.frank.demo.entity.EtlDataT1004;
  29. import com.frank.demo.entity.EtlDataT1009;
  30. import com.frank.demo.entity.EtlDataT1022;
  31. import com.frank.demo.util.api.ApiResponse;
  32. import com.frank.demo.util.dto.v1.PageRequestDto;
  33. import com.frank.demo.util.PageUtil;
  34. @Service
  35. public class SearchService {
  36. @Autowired
  37. EtlDataT1004Dao etlDataT1004Dao;
  38. @Autowired
  39. EtlDataT1009Dao etlDataT1009Dao;
  40. @Autowired
  41. EtlDataT1022Dao etlDataT1022Dao;
  42. private List<Word> words;
  43.         //本例是多数据源搜索,所以采用的是从三张表中获取相似公司名称的记录,再计算每条记录的相似度,最后统一放到list集合进行排序,最后采用内存分页返回(提示在数据量不是特别大的情景下可以这么做,如果数据量上百万,建议采用搜索引擎实现)
  44. public Map<String, Object> searchCompany(EtlCreatDueDiligenceRequestDto request, PageRequestDto page) {
  45. Map<String, Object> response = new LinkedHashMap<String, Object>();
  46. response.put(ApiResponse.KEY_MESSAGE, ApiResponse.MESSAGE_OK);
  47. List<EtlSearchCompanyResponseDto> data = new LinkedList<>();
  48. // 采用分词检索按照相似度高低进行排序(数据来源于三个地方,上交所,深交所,中小型企业股权转让系统)
  49. words = WordSegmenter.segWithStopWords(request.getCompanyName());//通过word分词器获取分词结果
  50. Sort shsort = new Sort(Direction.ASC,"f8");//列用数据库对匹配结果进行一次排序
  51. List<EtlDataT1004> shdatas = etlDataT1004Dao.findAll(new Specification<EtlDataT1004>() {
  52. @Override
  53. public Predicate toPredicate(Root<EtlDataT1004> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  54. List<Predicate> predicates = new LinkedList<>();
  55. for (Word word : words) {
  56. predicates.add(cb.like(root.get("f8").as(String.class), "%" + word.getText() + "%"));
  57. }
  58. Predicate[] p = new Predicate[predicates.size()];
  59. return cb.or(predicates.toArray(p));
  60. }
  61. },shsort);
  62. // 匹配度计算
  63. for (EtlDataT1004 t1004 : shdatas) {
  64. EtlSearchCompanyResponseDto responseDto = new EtlSearchCompanyResponseDto(t1004.getF8().split("/")[0], t1004.getF8().split("/")[1], t1004.getF1(), "1", t1004.getF9());
  65. int i = 0;
  66. for (Word word : words) {
  67. if (t1004.getF8().contains(word.getText())) {
  68. i++;
  69. }
  70. }
  71. responseDto.setCompanyLegal(t1004.getF11());
  72. responseDto.setMatching(i);
  73. data.add(responseDto);
  74. }
  75. Sort szsort = new Sort(Direction.ASC,"f3");
  76. List<EtlDataT1009> szDatas = etlDataT1009Dao.findAll(new Specification<EtlDataT1009>() {
  77. @Override
  78. public Predicate toPredicate(Root<EtlDataT1009> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  79. List<Predicate> predicates = new LinkedList<>();
  80. for (Word word : words) {
  81. predicates.add(cb.or(cb.like(root.get("f3").as(String.class), "%" + word.getText() + "%")));
  82. predicates.add(cb.or(cb.like(root.get("f4").as(String.class), "%" + word.getText() + "%")));
  83. }
  84. Predicate[] p = new Predicate[predicates.size()];
  85. return cb.or(predicates.toArray(p));
  86. }
  87. },szsort);
  88. // 匹配度计算
  89. for (EtlDataT1009 t1009 : szDatas) {
  90. EtlSearchCompanyResponseDto responseDto = new EtlSearchCompanyResponseDto(t1009.getF3(), t1009.getF4(), t1009.getF1(), "2", t1009.getF5());
  91. int i = 0;
  92. for (Word word : words) {
  93. if (t1009.getF3().contains(word.getText())) {
  94. i++;
  95. } else if (t1009.getF4().contains(word.getText())) {
  96. i++;
  97. }
  98. }
  99. responseDto.setMatching(i);
  100. data.add(responseDto);
  101. }
  102. Sort gzsort = new Sort(Direction.ASC,"f11");
  103. List<EtlDataT1022> gzDatas = etlDataT1022Dao.findAll(new Specification<EtlDataT1022>() {
  104. @Override
  105. public Predicate toPredicate(Root<EtlDataT1022> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  106. List<Predicate> predicates = new LinkedList<>();
  107. for (Word word : words) {
  108. predicates.add(cb.or(cb.like(root.get("f11").as(String.class), "%" + word.getText() + "%")));
  109. predicates.add(cb.or(cb.like(root.get("f12").as(String.class), "%" + word.getText() + "%")));
  110. }
  111. Predicate[] p = new Predicate[predicates.size()];
  112. return cb.or(predicates.toArray(p));
  113. }
  114. },gzsort);
  115. // 匹配度计算
  116. for (EtlDataT1022 t1022 : gzDatas) {
  117. EtlSearchCompanyResponseDto responseDto = new EtlSearchCompanyResponseDto(t1022.getF11(), t1022.getF12(), t1022.getF1(), "3", t1022.getF14());
  118. int i = 0;
  119. for (Word word : words) {
  120. if (t1022.getF11().contains(word.getText())) {
  121. i++;
  122. } else if (t1022.getF12().contains(word.getText())) {
  123. i++;
  124. }
  125. }
  126. responseDto.setCompanyLegal(t1022.getF15());
  127. responseDto.setMatching(i);
  128. data.add(responseDto);
  129. }
  130. // 排序分页
  131. PageUtil.searchCompanyComparator(data);
  132. List<EtlSearchCompanyResponseDto> pages = PageUtil.splitList(data, page.getSize(), page.getPage()-1);
  133. response.put(ApiResponse.KEY_DATA, pages);
  134. Map<String, Object> pageMap = new LinkedHashMap<>();
  135. int size = data.size() / page.getSize();
  136. if (data.size() % page.getSize() != 0) {
  137. size++;
  138. }
  139. pageMap.put("pageCount", size);
  140. response.put(ApiResponse.KEY_PAGE, pageMap);
  141. return response;
  142. }
  143. }

使用word分词器的朋友给个提醒,word分词器初次调用时会加载词库,所以建议大家在项目启动的时候默认去调用以下分词器的接口,这便于你在使用分词的时候不会等待很长时间,正常加载本例经测试10万级别的数据返回时间是1s内。

有疑问的朋友可以在评论中留言了,看到会第一时间回复!

喜欢朋友可以关注我的个人微信公众号哦,会同步更新相应技术,二维码见下图。


萌萌技术


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/610051
推荐阅读
相关标签
  

闽ICP备14008679号