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

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 questionOptions = new HashSet(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 getQuestionOptions() {
		return this.questionOptions;
	}

	public void setQuestionOptions(Set 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 employeeQuestionOptions = new HashSet(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 getEmployeeQuestionOptions() {
		return this.employeeQuestionOptions;
	}

	public void setEmployeeQuestionOptions(Set 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( "", "");
        	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 list=new ArrayList();
		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;
	}



你可能感兴趣的:(hibernate,java,SSH)