【发布时间】:2014-03-04 15:37:58
【问题描述】:
我需要在使用 Spring (4.0.2)/Hibernate(4.3.1)/MySQL 实现的网站上实现全局搜索。我决定为此使用 Hibernate Search(4.5.0)。
这似乎工作正常,但只有当我搜索确切的模式时。
想象一下,我在索引字段上有以下文本: "A história do Capuchinho e do Lobo Mau"
1) 如果我搜索“história”或“lobo mau”,查询将检索相应的索引实体,正如我所料。
2) 如果我搜索“historia”或“lobos maus”,搜索将不会检索到实体。
据我所知,应该可以配置 Hibernate Search 以执行比这更智能的搜索。谁能指出我实现这一目标的正确方向?请参阅下面我执行的实现的关键方面。谢谢!
这是“父”索引实体
@Entity
@Table(name="NEWS_HEADER")
@Indexed
public class NewsHeader implements Serializable {
static final long serialVersionUID = 20140301L;
private int id;
private String articleHeader;
private String language;
private Set<NewsParagraph> paragraphs = new HashSet<NewsParagraph>();
/**
* @return the id
*/
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
@DocumentId
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the articleHeader
*/
@Column(name="ARTICLE_HEADER")
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
public String getArticleHeader() {
return articleHeader;
}
/**
* @param articleHeader the articleHeader to set
*/
public void setArticleHeader(String articleHeader) {
this.articleHeader = articleHeader;
}
/**
* @return the language
*/
@Column(name="LANGUAGE")
public String getLanguage() {
return language;
}
/**
* @param language the language to set
*/
public void setLanguage(String language) {
this.language = language;
}
/**
* @return the paragraphs
*/
@OneToMany(mappedBy="newsHeader", fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@IndexedEmbedded
public Set<NewsParagraph> getParagraphs() {
return paragraphs;
}
// Other standard getters/setters go here
这是 IndexedEmbedded 实体
@Entity
@Table(name="NEWS_PARAGRAPH")
public class NewsParagraph implements Serializable {
static final long serialVersionUID = 20140302L;
private int id;
private String content;
private NewsHeader newsHeader;
/**
* @return the id
*/
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the content
*/
@Column(name="CONTENT")
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
public String getContent() {
return content;
}
// Other standard getters/setters go here
这是我的搜索方法,在我的 SearchDAOImpl 上实现
public class SearchDAOImpl extends DAOBasics implements SearchDAO {
...
public List<NewsHeader> searchParagraph(String patternStr) {
Session session = null;
Transaction tx;
List<NewsHeader> result = null;
try {
session = sessionFactory.getCurrentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
tx = fullTextSession.beginTransaction();
// Create native Lucene query using the query DSL
QueryBuilder queryBuilder = fullTextSession.getSearchFactory()
.buildQueryBuilder().forEntity(NewsHeader.class).get();
org.apache.lucene.search.Query luceneSearchQuery = queryBuilder
.keyword()
.onFields("articleHeader", "paragraphs.content")
.matching(patternStr)
.createQuery();
// Wrap Lucene query in a org.hibernate.Query
org.hibernate.Query hibernateQuery =
fullTextSession.createFullTextQuery(luceneSearchQuery, NewsHeader.class, NewsParagraph.class);
// Execute search
result = hibernateQuery.list();
} catch (Exception xcp) {
logger.error(xcp);
} finally {
if ((session != null) && (session.isOpen())) {
session.close();
}
}
return result;
}
...
}
【问题讨论】: