一。假设现在有这么一个应用场景。数据库里存放了大量文章,我们想要通过输入关键字,从数据库中检索出相关的文章。
1.建立Article Entity:
public class Article {
private String id; //ID
private String title; //标题
private String content; //内容
private String isPublication; //发布状态
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getIsPublication() {
return isPublication;
}
public void setIsPublication(String isPublication) {
this.isPublication = isPublication;
}
}
2.建立索引:
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
public class IndexArticle {
@PersistenceContext
protected EntityManager entityManager;
public void indexArticle(){
// ......具体编码不细写了
// List<Article> articles = articleService.findList(null, null, null, first, count);
// for (Article article : articless) {
// index(article);
// }
}
public void index(Article article){
//Hibernate Search JPA
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
fullTextEntityManager.index(articles);
}
}
3.检索关键字:
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.Version;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.wltea.analyzer.lucene.IKAnalyzer;
import com.dowik.dwshop.mall.entity.Article;
public class SearchArticle {
@PersistenceContext
protected EntityManager entityManager;
public List<Article> searchResult(String keyword){
try {
//要搜索的关键词
keyword = QueryParser.escape(keyword);
//解析器,中文分词工具
QueryParser titleParser = new QueryParser(Version.LUCENE_35, "title", new IKAnalyzer());
titleParser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query titleQuery = titleParser.parse(keyword);
//模糊搜索标题
FuzzyQuery titleFuzzyQuery = new FuzzyQuery(new Term("title", keyword), 0.5F);
//按词条搜索内容
Query contentQuery = new TermQuery(new Term("content", keyword));
//按词条搜索发布状态
Query isPublicationQuery = new TermQuery(new Term("isPublication", "true"));
//全文检索(标题搜索+内容搜索)
BooleanQuery textQuery = new BooleanQuery();
textQuery.add(titleQuery, Occur.SHOULD);
textQuery.add(titleFuzzyQuery, Occur.SHOULD);
textQuery.add(contentQuery, Occur.SHOULD);
//发布状态+全文检索
BooleanQuery query = new BooleanQuery();
query.add(isPublicationQuery, Occur.MUST);
query.add(textQuery, Occur.MUST);
//Hibernate Search JPA
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, Articles.class);
List<Article> resultList = fullTextQuery.getResultList();
return resultList;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
以上三个步骤构建了一个简单的 Hibernate Search JPA + Lucene 简单应用实例。
二。补充实例
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.Version;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.wltea.analyzer.lucene.IKAnalyzer;
public class ProductSearch {
@PersistenceContext
protected EntityManager entityManager;
public List<ProductEntity> ProductInde(String inputKeyWord, BigDecimal startPrice, BigDecimal endPrice, String sortingType){
//要搜索的关键词
inputKeyWord = QueryParser.escape(inputKeyWord);
try {
//关键字检索
Query keywordQuery = new QueryParser(Version.LUCENE_35, "keyword", new IKAnalyzer()).parse(inputKeyWord);
//商品名称检索
QueryParser nameParser = new QueryParser(Version.LUCENE_35, "name", new IKAnalyzer());
nameParser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query nameQuery = nameParser.parse(inputKeyWord);
//商品名称模糊检索
FuzzyQuery nameFuzzyQuery = new FuzzyQuery(new Term("name", inputKeyWord), 0.5F);
//商品简介检索
TermQuery introductionQuery = new TermQuery(new Term("introduction", inputKeyWord));
//是否上架
TermQuery isMarketableQuery = new TermQuery(new Term("isMarketable", inputKeyWord));
//是否是非售商品
TermQuery isGiftQuery = new TermQuery(new Term("isGiftQuery", inputKeyWord));
//全文检索(商品名称+商品简介)
BooleanQuery textQuery = new BooleanQuery();
textQuery.add(keywordQuery, Occur.SHOULD);
textQuery.add(nameQuery, Occur.SHOULD);
textQuery.add(nameFuzzyQuery, Occur.SHOULD);
textQuery.add(introductionQuery, Occur.SHOULD);
//发布状态+全文检索
BooleanQuery query = new BooleanQuery();
query.add(isMarketableQuery, Occur.MUST);
query.add(isGiftQuery, Occur.MUST);
query.add(textQuery, Occur.MUST);
//价格范围检索
if(startPrice!=null && endPrice!=null && startPrice.compareTo(endPrice)>0){
BigDecimal temp = startPrice;
startPrice = endPrice;
endPrice = temp;
} else if (startPrice!=null && endPrice!=null && startPrice.compareTo(new BigDecimal(0))>=0 && endPrice.compareTo(new BigDecimal(0))>=0) {
NumericRangeQuery<Double> priceRangeQuery = NumericRangeQuery.newDoubleRange("price", startPrice.doubleValue(), endPrice.doubleValue(), true, true);
query.add(priceRangeQuery, Occur.MUST);
} else if(startPrice != null && startPrice.compareTo(new BigDecimal(0)) >= 0) {
NumericRangeQuery<Double> priceRangeQuery = NumericRangeQuery.newDoubleRange("price", startPrice.doubleValue(), null, true, false);
query.add(priceRangeQuery, Occur.MUST);
} else if(endPrice != null && endPrice.compareTo(new BigDecimal(0)) >= 0) {
NumericRangeQuery<Double> priceRangeQuery = NumericRangeQuery.newDoubleRange("price", null, endPrice.doubleValue(), false, true);
query.add(priceRangeQuery, Occur.MUST);
}
//Hibernate Search JPA
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, ProductEntity.class);
//检索排序
SortField[] sortFields = null;
if("priceAsc".equalsIgnoreCase(sortingType)){
sortFields = new SortField[]{new SortField("price", SortField.DOUBLE, false), new SortField("create", SortField.LONG, true)};
} else if("priceDesc".equalsIgnoreCase(sortingType)) {
sortFields = new SortField[]{new SortField("price", SortField.DOUBLE, true), new SortField("createDate", SortField.LONG, true)};
} else if("salesDesc".equalsIgnoreCase(sortingType)) {
sortFields = new SortField[]{new SortField("sales", SortField.INT, true), new SortField("createDate", SortField.LONG, true)};
} else if("dateDesc".equalsIgnoreCase(sortingType)) {
sortFields = new SortField[]{new SortField("createDate", SortField.LONG, true)};
} else {
sortFields = new SortField[]{new SortField("isTop", SortField.STRING, true), new SortField(null, SortField.SCORE), new SortField("modifyDate", SortField.LONG, true)};
}
fullTextQuery.setSort(new Sort(sortFields));
//获取返回结果集
List<ProductEntity> resultList = fullTextQuery.getResultList();
return resultList;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
补充例子更加贴合实际业务需求,通过输入关键字,从数据库中检索出相关的商品。
多了Lucene数值范围的检索NumericRangeQuery,和检索结果的排序SortField。