LegislationServiceImpl.java 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package com.winhc.phoenix.example.service.impl;
  2. import com.winhc.phoenix.example.dao.SearchDao;
  3. import com.winhc.phoenix.example.service.LegislationService;
  4. import com.winhc.phoenix.example.util.BigDecimalUtil;
  5. import com.winhc.phoenix.example.util.company.search.CompanyIndexUtils;
  6. import com.winhc.phoenix.example.vo.legislation.LegislationSearchType;
  7. import com.winhc.phoenix.example.vo.legislation.LegislationSearchVo;
  8. import lombok.AllArgsConstructor;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.apache.commons.lang3.StringUtils;
  11. import org.elasticsearch.common.lucene.search.function.CombineFunction;
  12. import org.elasticsearch.index.query.BoolQueryBuilder;
  13. import org.elasticsearch.index.query.QueryBuilder;
  14. import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
  15. import org.elasticsearch.index.query.functionscore.ScriptScoreFunctionBuilder;
  16. import org.elasticsearch.script.Script;
  17. import org.springframework.stereotype.Service;
  18. import java.time.LocalDate;
  19. import java.util.ArrayList;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.Map;
  23. import static org.elasticsearch.index.query.QueryBuilders.*;
  24. /**
  25. * @author: XuJiakai
  26. * 2022/9/2 11:38
  27. */
  28. @Slf4j
  29. @Service
  30. @AllArgsConstructor
  31. public class LegislationServiceImpl implements LegislationService {
  32. private final SearchDao searchDao;
  33. public static final String index = "legislation_info_fx_v1";
  34. public static final String type = "legislation_info_fx_type";
  35. private static final List<String> highlightField = new ArrayList<String>() {{
  36. add("title");
  37. add("content");
  38. add("title.keyword");
  39. }};
  40. private static final String SCRIPT_TEXT = "double d = 1.0d;if(doc['effect'].value!=null){String effect =doc['effect'].value;if(effect.contains(\"法律\")){if(\"法律\".equals(effect)){if(\"全国人民代表大会\".equals(doc['agency.keyword'].value)){d+=7.9;}else if(\"全国人大常委会\".equals(doc['agency.keyword'].value)){d+=7.8;}}else if (\"法律解释\".equals(effect)){d+=6.7}}else if(\"司法解释\".equals(effect)){d+=6.5;}else if(\"司法指导性文件\".equals(effect)){d+=5.0;}else if(\"行政法规\".equals(effect)){d+=5.0;}else if(effect.contains(\"地方性法规\")){if(effect.contains(\"市地方性法规\")||effect.contains(\"州地方性法规\")){d+=4.0;}else{d+=4.5;}}else if(\"部门规章\".equals(effect)){d+=3.8}else if(\"地方政府规章\".equals(effect)){if(doc['agency.keyword'].value!=null){String agency = doc['agency.keyword'].value;if(agency.contains(\"省人民政府\")||agency.contains(\"自治区人民政府\")||agency.equals(\"北京市人民政府\")||agency.equals(\"上海市人民政府\")||agency.equals(\"天津市人民政府\")||agency.equals(\"重庆市人民政府\")){d+=3.3}else{d+=3.0}}}else if(\"地方司法文件\".equals(effect)){if(doc['agency.keyword'].value!=null){String agency = doc['agency.keyword'].value;if(agency.contains(\"高级人民法院\")||agency.contains(\"省人民检察院\")){d+=2.5;}else{d+=2.0}}}else if(effect.contains(\"规范性文件\")){if(effect.contains(\"国务院\")){d+=1.8;}else if(effect.contains(\"部门\")){d+=1.6;}else if (effect.contains(\"地方\")){if(doc['agency.keyword'].value!=null){String agency = doc['agency.keyword'].value;if(agency.contains(\"省人民政府\")||agency.contains(\"自治区人民政府\")||agency.equals(\"北京市人民政府\")||agency.equals(\"上海市人民政府\")||agency.equals(\"天津市人民政府\")||agency.equals(\"重庆市人民政府\")){d+=1.5;}else{d+=1;}}}}}String timeliness = doc['timeliness'].value;if(timeliness!=null){if(timeliness.contains(\"失效\")){d=d/2;}if(timeliness.contains(\"已被修改\")){d = d-0.3;}}long date = doc['implement_date'].value/(24l*60*60*365*1000);if(date >20){d=d + Math.abs(20-date)*params.der;}return d;";
  41. private static QueryBuilder queryUnit(LegislationSearchType queryScope, String content) {
  42. BoolQueryBuilder boolQuery = boolQuery();
  43. switch (queryScope) {
  44. case TITLE:
  45. boolQuery.filter(boolQuery()
  46. .should(matchQuery("title", content))
  47. .should(termQuery("title.keyword", content))
  48. );
  49. boolQuery.should(disMaxQuery()
  50. .add(matchQuery("title.standard", content).minimumShouldMatch("100%").boost(20))
  51. .add(matchQuery("title.trim", content).boost(20).minimumShouldMatch("100%"))
  52. .add(termQuery("title.keyword", content).boost(100))
  53. .tieBreaker(0.3f)
  54. );
  55. break;
  56. case CONTENT:
  57. boolQuery.should(disMaxQuery()
  58. .add(matchPhraseQuery("content", content).boost(25))
  59. .add(matchQuery("content", content).boost(20).minimumShouldMatch("100%"))
  60. .add(matchQuery("content", content).boost(2))
  61. );
  62. break;
  63. default:
  64. boolQuery.should(boolQuery().filter(boolQuery()
  65. // .should(matchQuery("content", content).minimumShouldMatch("100%"))
  66. .should(matchQuery("title", content))
  67. .should(termQuery("title.keyword", content))
  68. ).boost(0));
  69. boolQuery.should(boolQuery().filter(boolQuery()
  70. .should(matchPhraseQuery("content", content))
  71. ).boost(25));
  72. boolQuery.should(boolQuery().filter(boolQuery()
  73. .should(matchQuery("content", content).boost(20).minimumShouldMatch("100%"))
  74. ).boost(20));
  75. boolQuery.should(boolQuery().filter(boolQuery()
  76. .should(matchQuery("content", content))
  77. ).boost(2));
  78. boolQuery.should(boolQuery().should(disMaxQuery()
  79. // .add(matchPhraseQuery("content", content).boost(25))
  80. // .add(matchQuery("content", content).boost(20).minimumShouldMatch("100%"))
  81. // .add(matchQuery("content", content).boost(2))
  82. .add(disMaxQuery()
  83. .add(matchQuery("title.standard", content).minimumShouldMatch("100%").boost(20))
  84. .add(matchQuery("title.trim", content).boost(20).minimumShouldMatch("100%"))
  85. .add(termQuery("title.keyword", content).boost(100))
  86. .tieBreaker(0.3f))
  87. ));
  88. break;
  89. }
  90. return boolQuery;
  91. }
  92. @Override
  93. public Object search(LegislationSearchVo of) {
  94. log.info("search legislation keyword: {}", of.getContent());
  95. BoolQueryBuilder boolQuery = boolQuery();
  96. for (Map.Entry<String, LegislationSearchType> entry : of.getContent().entrySet()) {
  97. String content = entry.getKey();
  98. LegislationSearchType value = entry.getValue();
  99. for (String s : content.split(" ")) {
  100. if (StringUtils.isBlank(s)) {
  101. continue;
  102. }
  103. boolQuery.must(queryUnit(value, s));
  104. }
  105. }
  106. LocalDate now = LocalDate.now();
  107. int year = now.getYear();
  108. double d = year <= 1990 ? 0 : BigDecimalUtil.div(4, year - 1990, 4);
  109. Script script = CompanyIndexUtils.getScript(SCRIPT_TEXT, new HashMap<String, Object>(1) {
  110. {
  111. put("der", d);
  112. }
  113. });
  114. FunctionScoreQueryBuilder function = functionScoreQuery(boolQuery, new ScriptScoreFunctionBuilder(script))
  115. .boostMode(CombineFunction.MULTIPLY);
  116. String preference = of.getPreference();
  117. Object search = searchDao.search(index
  118. , type
  119. // , boolQuery
  120. , function
  121. , null
  122. , null
  123. , null
  124. , of.getFrom()
  125. , of.getSize()
  126. , preference
  127. , highlightField
  128. , null
  129. );
  130. return search;
  131. }
  132. }