原文地址:https://blog.csdn.net/qq_33663251/article/details/54928478
Hibernate Search使用以及搜索结果高亮显视
1、首先说一下需求
有两个实体:问题实体(Question)和选项实体(QuestionOption),两个实体间是一对多关系,需求如下:根据问题(questionContent字段)或选项(questionOptionContent字段)进行搜索,并将搜索结果高亮显示。
2、所需jar包(gradle项目)
-
'org.hibernate:hibernate-core:5.0.9.Final',
-
'org.hibernate:hibernate-java8:5.0.9.Final',
-
'org.hibernate:hibernate-ehcache:5.0.9.Final',
-
'org.hibernate:hibernate-entitymanager:5.0.9.Final',
-
'org.hibernate:hibernate-search-engine:5.5.4.Final',
-
'org.hibernate:hibernate-search-orm:5.5.4.Final',
-
'org.apache.lucene:lucene-core:5.3.1',
-
'org.apache.lucene:lucene-analyzers-smartcn:5.3.1',
-
'org.apache.lucene:lucene-highlighter:5.3.1'
3、实体注解如下(具体参照hibernate search 官网):
-
import java.util.HashSet;
-
import java.util.Set;
-
import javax.persistence.Column;
-
import javax.persistence.Entity;
-
import javax.persistence.FetchType;
-
import javax.persistence.GeneratedValue;
-
import static javax.persistence.GenerationType.IDENTITY;
-
import javax.persistence.Id;
-
import javax.persistence.JoinColumn;
-
import javax.persistence.JoinTable;
-
import javax.persistence.ManyToMany;
-
import javax.persistence.OneToMany;
-
import javax.persistence.Table;
-
import javax.persistence.UniqueConstraint;
-
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
-
import org.hibernate.search.annotations.Analyze;
-
import org.hibernate.search.annotations.Analyzer;
-
import org.hibernate.search.annotations.Field;
-
import org.hibernate.search.annotations.Index;
-
import org.hibernate.search.annotations.Indexed;
-
import org.hibernate.search.annotations.IndexedEmbedded;
-
import org.hibernate.search.annotations.Store;
-
/**
-
* Question generated by hbm2java
-
* updated by 馬輝 2016-11-29 21:46
-
*/
-
@Indexed
-
@Entity
-
@Table(name = "question", catalog = "mryt", uniqueConstraints = @UniqueConstraint(columnNames = "question_sn"))
-
@Analyzer(impl=SmartChineseAnalyzer.class)//分词器
-
public class Question implements java.io.Serializable {
-
private static final long serialVersionUID = 4651161939667149753L;
-
private Integer id;
-
private String questionSn;
-
private String questionContent;
-
private Set<QuestionOption> questionOptions = new HashSet<QuestionOption>(0);
-
@Id
-
@GeneratedValue(strategy = IDENTITY)
-
@Column(name = "id", unique = true, nullable = false)
-
public Integer getId() {
-
return this.id;
-
}
-
public void setId(Integer id) {
-
this.id = id;
-
}
-
@Column(name = "question_sn", unique = true, length = 50)
-
public String getQuestionSn() {
-
return this.questionSn;
-
}
-
public void setQuestionSn(String questionSn) {
-
this.questionSn = questionSn;
-
}
-
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.YES)
-
@Column(name = "questionContent", length = 65535)
-
public String getQuestionContent() {
-
return this.questionContent;
-
}
-
public void setQuestionContent(String questionContent) {
-
this.questionContent = questionContent;
-
}
-
@IndexedEmbedded
-
@OneToMany(targetEntity=QuestionOption.class, fetch = FetchType.LAZY, mappedBy = "question")
-
public Set<QuestionOption> getQuestionOptions() {
-
return this.questionOptions;
-
}
-
public void setQuestionOptions(Set<QuestionOption> questionOptions) {
-
this.questionOptions = questionOptions;
-
}
-
}
-
import java.util.HashSet;
-
import java.util.Set;
-
import javax.persistence.Column;
-
import javax.persistence.Entity;
-
import javax.persistence.FetchType;
-
import javax.persistence.Id;
-
import javax.persistence.JoinColumn;
-
import javax.persistence.ManyToOne;
-
import javax.persistence.OneToMany;
-
import javax.persistence.Table;
-
import javax.persistence.UniqueConstraint;
-
import org.hibernate.search.annotations.Analyze;
-
import org.hibernate.search.annotations.Field;
-
import org.hibernate.search.annotations.Index;
-
import org.hibernate.search.annotations.Indexed;
-
import org.hibernate.search.annotations.Store;
-
/**
-
* QuestionOption generated by hbm2java
-
* updated by 馬輝 2016-11-29 21:48
-
*/
-
@Indexed
-
@Entity
-
@Table(name = "question_option", catalog = "mryt", uniqueConstraints = @UniqueConstraint(columnNames = "question_option_sn"))
-
public class QuestionOption implements java.io.Serializable {
-
private static final long serialVersionUID = 3055805431841974260L;
-
private int id;
-
private Question question;
-
private String questionOptionSn;
-
private String questionOptionContent;
-
private boolean isAnswer;
-
private Set<EmployeeQuestionOption> employeeQuestionOptions = new HashSet<EmployeeQuestionOption>(0);
-
@Id
-
@Column(name = "id", unique = true, nullable = false)
-
public int getId() {
-
return this.id;
-
}
-
public void setId(int id) {
-
this.id = id;
-
}
-
@ManyToOne(targetEntity=Question.class,fetch = FetchType.LAZY)
-
@JoinColumn(name = "question_sn",referencedColumnName="question_sn", nullable = false)
-
public Question getQuestion() {
-
return this.question;
-
}
-
public void setQuestion(Question question) {
-
this.question = question;
-
}
-
@Column(name = "question_option_sn", unique = true, nullable = false, length = 60)
-
public String getQuestionOptionSn() {
-
return this.questionOptionSn;
-
}
-
public void setQuestionOptionSn(String questionOptionSn) {
-
this.questionOptionSn = questionOptionSn;
-
}
-
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.YES)
-
@Column(name = "question_option_content", nullable = false, length = 65535)
-
public String getQuestionOptionContent() {
-
return this.questionOptionContent;
-
}
-
public void setQuestionOptionContent(String questionOptionContent) {
-
this.questionOptionContent = questionOptionContent;
-
}
-
@Column(name = "is_answer", nullable = false)
-
public boolean getIsAnswer() {
-
return isAnswer;
-
}
-
public void setIsAnswer(boolean isAnswer) {
-
this.isAnswer = isAnswer;
-
}
-
@OneToMany(targetEntity=EmployeeQuestionOption.class, fetch = FetchType.LAZY, mappedBy = "questionOption")
-
public Set<EmployeeQuestionOption> getEmployeeQuestionOptions() {
-
return this.employeeQuestionOptions;
-
}
-
public void setEmployeeQuestionOptions(Set<EmployeeQuestionOption> employeeQuestionOptions) {
-
this.employeeQuestionOptions = employeeQuestionOptions;
-
}
-
}
4、搜索以及高亮
-
/**
-
* @method 私有方法(打包高亮问题json)
-
* @param question
-
* @author mahui
-
* @return JSONObject
-
*/
-
private JSONObject packSearchQuestion(Question question,Query luceneQuery,String str){
-
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter( "<span style='color:red;'>", "</span>");
-
QueryScorer qs = new QueryScorer(luceneQuery);
-
Highlighter highlighter = new Highlighter( formatter, qs);
-
Analyzer analyzer = new SmartChineseAnalyzer();
-
JSONObject jsonObject=new JSONObject();
-
JSONObject qjo=new JSONObject();
-
qjo.put("questionSn", question.getQuestionSn());
-
//存放高亮问题
-
String questionContent="";
-
try {
-
questionContent = highlighter.getBestFragment(analyzer, str, question.getQuestionContent());
-
} catch (InvalidTokenOffsetsException e) {
-
e.printStackTrace();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
//重新封装问题
-
if(questionContent!=null&&questionContent.trim().length()>0){
-
qjo.put("questionContent", questionContent);
-
}else{
-
qjo.put("questionContent", question.getQuestionContent());
-
}
-
JSONArray array=new JSONArray();
-
int i=0;
-
//选项高亮
-
for(QuestionOption questionOption:question.getQuestionOptions()){
-
JSONObject jo=new JSONObject();
-
jo.put("order", (char)('A'+i));
-
jo.put("optionSn", questionOption.getQuestionOptionSn());
-
//存放高亮选项
-
String optionContent="";
-
try {
-
optionContent = highlighter.getBestFragment(analyzer, str, questionOption.getQuestionOptionContent());
-
} catch (InvalidTokenOffsetsException e) {
-
e.printStackTrace();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
//重新封装选项
-
if(optionContent!=null&&optionContent.trim().length()>0){
-
jo.put("optionContent", optionContent);
-
}else{
-
jo.put("optionContent", questionOption.getQuestionOptionContent());
-
}
-
jo.put("isAnswer", questionOption.getIsAnswer());
-
array.add(jo);
-
i++;
-
}
-
jsonObject.put("question", qjo);
-
jsonObject.put("options", array);
-
return jsonObject;
-
}
-
/**
-
* @method 全文检索问题
-
* @param str
-
* @author mahui
-
* @return JSONArray
-
*/
-
@SuppressWarnings("unchecked")
-
@Override
-
public JSONArray fullTextQuery(String str) {
-
FullTextSession fullTextSession = Search.getFullTextSession(getSession());
-
List<Question> list=new ArrayList<Question>();
-
try {
-
fullTextSession.createIndexer().startAndWait();
-
} catch (InterruptedException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
QueryBuilder qb=fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Question.class).get();
-
org.apache.lucene.search.Query luceneQuery = qb
-
.keyword()
-
.onFields("questionContent", "questionOptions.questionOptionContent")
-
.matching(str)
-
.createQuery();
-
FullTextQuery query = fullTextSession.createFullTextQuery(luceneQuery, Question.class);
-
list=query.setMaxResults(2).list();
-
JSONArray array=new JSONArray();
-
for(Question question:list){
-
array.add(packSearchQuestion(question,luceneQuery,str));
-
}
-
return array;
-
}