Hibernate Search使用以及搜索结果高亮显示

本是古典 何须时尚 2022-05-13 03:12 361阅读 0赞

原文地址:https://blog.csdn.net/qq_33663251/article/details/54928478

Hibernate Search使用以及搜索结果高亮显视

1、首先说一下需求

有两个实体:问题实体(Question)和选项实体(QuestionOption),两个实体间是一对多关系,需求如下:根据问题(questionContent字段)或选项(questionOptionContent字段)进行搜索,并将搜索结果高亮显示。

2、所需jar包(gradle项目)

  1. 'org.hibernate:hibernate-core:5.0.9.Final',
  2. 'org.hibernate:hibernate-java8:5.0.9.Final',
  3. 'org.hibernate:hibernate-ehcache:5.0.9.Final',
  4. 'org.hibernate:hibernate-entitymanager:5.0.9.Final',
  5. 'org.hibernate:hibernate-search-engine:5.5.4.Final',
  6. 'org.hibernate:hibernate-search-orm:5.5.4.Final',
  7. 'org.apache.lucene:lucene-core:5.3.1',
  8. 'org.apache.lucene:lucene-analyzers-smartcn:5.3.1',
  9. 'org.apache.lucene:lucene-highlighter:5.3.1'

3、实体注解如下(具体参照hibernate search 官网):

  1. import java.util.HashSet;
  2. import java.util.Set;
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.FetchType;
  6. import javax.persistence.GeneratedValue;
  7. import static javax.persistence.GenerationType.IDENTITY;
  8. import javax.persistence.Id;
  9. import javax.persistence.JoinColumn;
  10. import javax.persistence.JoinTable;
  11. import javax.persistence.ManyToMany;
  12. import javax.persistence.OneToMany;
  13. import javax.persistence.Table;
  14. import javax.persistence.UniqueConstraint;
  15. import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
  16. import org.hibernate.search.annotations.Analyze;
  17. import org.hibernate.search.annotations.Analyzer;
  18. import org.hibernate.search.annotations.Field;
  19. import org.hibernate.search.annotations.Index;
  20. import org.hibernate.search.annotations.Indexed;
  21. import org.hibernate.search.annotations.IndexedEmbedded;
  22. import org.hibernate.search.annotations.Store;
  23. /**
  24. * Question generated by hbm2java
  25. * updated by 馬輝 2016-11-29 21:46
  26. */
  27. @Indexed
  28. @Entity
  29. @Table(name = "question", catalog = "mryt", uniqueConstraints = @UniqueConstraint(columnNames = "question_sn"))
  30. @Analyzer(impl=SmartChineseAnalyzer.class)//分词器
  31. public class Question implements java.io.Serializable {
  32. private static final long serialVersionUID = 4651161939667149753L;
  33. private Integer id;
  34. private String questionSn;
  35. private String questionContent;
  36. private Set<QuestionOption> questionOptions = new HashSet<QuestionOption>(0);
  37. @Id
  38. @GeneratedValue(strategy = IDENTITY)
  39. @Column(name = "id", unique = true, nullable = false)
  40. public Integer getId() {
  41. return this.id;
  42. }
  43. public void setId(Integer id) {
  44. this.id = id;
  45. }
  46. @Column(name = "question_sn", unique = true, length = 50)
  47. public String getQuestionSn() {
  48. return this.questionSn;
  49. }
  50. public void setQuestionSn(String questionSn) {
  51. this.questionSn = questionSn;
  52. }
  53. @Field(index=Index.YES, analyze=Analyze.YES, store=Store.YES)
  54. @Column(name = "questionContent", length = 65535)
  55. public String getQuestionContent() {
  56. return this.questionContent;
  57. }
  58. public void setQuestionContent(String questionContent) {
  59. this.questionContent = questionContent;
  60. }
  61. @IndexedEmbedded
  62. @OneToMany(targetEntity=QuestionOption.class, fetch = FetchType.LAZY, mappedBy = "question")
  63. public Set<QuestionOption> getQuestionOptions() {
  64. return this.questionOptions;
  65. }
  66. public void setQuestionOptions(Set<QuestionOption> questionOptions) {
  67. this.questionOptions = questionOptions;
  68. }
  69. }
  1. import java.util.HashSet;
  2. import java.util.Set;
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.FetchType;
  6. import javax.persistence.Id;
  7. import javax.persistence.JoinColumn;
  8. import javax.persistence.ManyToOne;
  9. import javax.persistence.OneToMany;
  10. import javax.persistence.Table;
  11. import javax.persistence.UniqueConstraint;
  12. import org.hibernate.search.annotations.Analyze;
  13. import org.hibernate.search.annotations.Field;
  14. import org.hibernate.search.annotations.Index;
  15. import org.hibernate.search.annotations.Indexed;
  16. import org.hibernate.search.annotations.Store;
  17. /**
  18. * QuestionOption generated by hbm2java
  19. * updated by 馬輝 2016-11-29 21:48
  20. */
  21. @Indexed
  22. @Entity
  23. @Table(name = "question_option", catalog = "mryt", uniqueConstraints = @UniqueConstraint(columnNames = "question_option_sn"))
  24. public class QuestionOption implements java.io.Serializable {
  25. private static final long serialVersionUID = 3055805431841974260L;
  26. private int id;
  27. private Question question;
  28. private String questionOptionSn;
  29. private String questionOptionContent;
  30. private boolean isAnswer;
  31. private Set<EmployeeQuestionOption> employeeQuestionOptions = new HashSet<EmployeeQuestionOption>(0);
  32. @Id
  33. @Column(name = "id", unique = true, nullable = false)
  34. public int getId() {
  35. return this.id;
  36. }
  37. public void setId(int id) {
  38. this.id = id;
  39. }
  40. @ManyToOne(targetEntity=Question.class,fetch = FetchType.LAZY)
  41. @JoinColumn(name = "question_sn",referencedColumnName="question_sn", nullable = false)
  42. public Question getQuestion() {
  43. return this.question;
  44. }
  45. public void setQuestion(Question question) {
  46. this.question = question;
  47. }
  48. @Column(name = "question_option_sn", unique = true, nullable = false, length = 60)
  49. public String getQuestionOptionSn() {
  50. return this.questionOptionSn;
  51. }
  52. public void setQuestionOptionSn(String questionOptionSn) {
  53. this.questionOptionSn = questionOptionSn;
  54. }
  55. @Field(index=Index.YES, analyze=Analyze.YES, store=Store.YES)
  56. @Column(name = "question_option_content", nullable = false, length = 65535)
  57. public String getQuestionOptionContent() {
  58. return this.questionOptionContent;
  59. }
  60. public void setQuestionOptionContent(String questionOptionContent) {
  61. this.questionOptionContent = questionOptionContent;
  62. }
  63. @Column(name = "is_answer", nullable = false)
  64. public boolean getIsAnswer() {
  65. return isAnswer;
  66. }
  67. public void setIsAnswer(boolean isAnswer) {
  68. this.isAnswer = isAnswer;
  69. }
  70. @OneToMany(targetEntity=EmployeeQuestionOption.class, fetch = FetchType.LAZY, mappedBy = "questionOption")
  71. public Set<EmployeeQuestionOption> getEmployeeQuestionOptions() {
  72. return this.employeeQuestionOptions;
  73. }
  74. public void setEmployeeQuestionOptions(Set<EmployeeQuestionOption> employeeQuestionOptions) {
  75. this.employeeQuestionOptions = employeeQuestionOptions;
  76. }
  77. }

4、搜索以及高亮

  1. /**
  2. * @method 私有方法(打包高亮问题json)
  3. * @param question
  4. * @author mahui
  5. * @return JSONObject
  6. */
  7. private JSONObject packSearchQuestion(Question question,Query luceneQuery,String str){
  8. SimpleHTMLFormatter formatter = new SimpleHTMLFormatter( "<span style='color:red;'>", "</span>");
  9. QueryScorer qs = new QueryScorer(luceneQuery);
  10. Highlighter highlighter = new Highlighter( formatter, qs);
  11. Analyzer analyzer = new SmartChineseAnalyzer();
  12. JSONObject jsonObject=new JSONObject();
  13. JSONObject qjo=new JSONObject();
  14. qjo.put("questionSn", question.getQuestionSn());
  15. //存放高亮问题
  16. String questionContent="";
  17. try {
  18. questionContent = highlighter.getBestFragment(analyzer, str, question.getQuestionContent());
  19. } catch (InvalidTokenOffsetsException e) {
  20. e.printStackTrace();
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. //重新封装问题
  25. if(questionContent!=null&&questionContent.trim().length()>0){
  26. qjo.put("questionContent", questionContent);
  27. }else{
  28. qjo.put("questionContent", question.getQuestionContent());
  29. }
  30. JSONArray array=new JSONArray();
  31. int i=0;
  32. //选项高亮
  33. for(QuestionOption questionOption:question.getQuestionOptions()){
  34. JSONObject jo=new JSONObject();
  35. jo.put("order", (char)('A'+i));
  36. jo.put("optionSn", questionOption.getQuestionOptionSn());
  37. //存放高亮选项
  38. String optionContent="";
  39. try {
  40. optionContent = highlighter.getBestFragment(analyzer, str, questionOption.getQuestionOptionContent());
  41. } catch (InvalidTokenOffsetsException e) {
  42. e.printStackTrace();
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. //重新封装选项
  47. if(optionContent!=null&&optionContent.trim().length()>0){
  48. jo.put("optionContent", optionContent);
  49. }else{
  50. jo.put("optionContent", questionOption.getQuestionOptionContent());
  51. }
  52. jo.put("isAnswer", questionOption.getIsAnswer());
  53. array.add(jo);
  54. i++;
  55. }
  56. jsonObject.put("question", qjo);
  57. jsonObject.put("options", array);
  58. return jsonObject;
  59. }
  60. /**
  61. * @method 全文检索问题
  62. * @param str
  63. * @author mahui
  64. * @return JSONArray
  65. */
  66. @SuppressWarnings("unchecked")
  67. @Override
  68. public JSONArray fullTextQuery(String str) {
  69. FullTextSession fullTextSession = Search.getFullTextSession(getSession());
  70. List<Question> list=new ArrayList<Question>();
  71. try {
  72. fullTextSession.createIndexer().startAndWait();
  73. } catch (InterruptedException e) {
  74. // TODO Auto-generated catch block
  75. e.printStackTrace();
  76. }
  77. QueryBuilder qb=fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Question.class).get();
  78. org.apache.lucene.search.Query luceneQuery = qb
  79. .keyword()
  80. .onFields("questionContent", "questionOptions.questionOptionContent")
  81. .matching(str)
  82. .createQuery();
  83. FullTextQuery query = fullTextSession.createFullTextQuery(luceneQuery, Question.class);
  84. list=query.setMaxResults(2).list();
  85. JSONArray array=new JSONArray();
  86. for(Question question:list){
  87. array.add(packSearchQuestion(question,luceneQuery,str));
  88. }
  89. return array;
  90. }

发表评论

表情:
评论列表 (有 0 条评论,361人围观)

还没有评论,来说两句吧...

相关阅读