我需要在我使用Spring(4.0.2)/ Hibernate(4.3.1)/ MySQL实现的网站上实现全局搜索。我决定使用Hibernate Search(4.5.0)。
这似乎工作正常,但只有在我搜索确切的模式时才会正常工作。
想象一下,我在索引字段上有以下文字: “一个组织做Capuchinho e做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;
}
...
}
答案 0 :(得分:2)
您可以配置,也可以使用标准语言分析器,例如PortugueseAnalyzer
。我建议从现有的分析器开始,并在必要时创建自己的分析器,将其作为调整过滤器链的起点。
您可以使用字段的@Analyzer
注释进行设置:
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO, analyzer = @Analyzer(impl = org.apache.lucene.analysis.pt.PortugueseAnalyzer.class))
或者您可以将该分析器设置为该类的默认值,如果您放置@analyzer
注释,则代之以该类的头部。
答案 1 :(得分:2)
这就是我最终要解决的问题。
在实体级别配置AnalyzerDef。在其中,使用LowerCaseFilterFactory,ASCIIFoldingFilterFactory和SnowballPorterFilterFactory来实现我需要的过滤类型。
@AnalyzerDef(name = "customAnalyzer",
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
@TokenFilterDef(factory = SnowballPorterFilterFactory.class)
})
public class NewsHeader implements Serializable {
...
}
为我要索引的每个字段添加此表示法,在Parent实体或其IndexedEmbedded对应项中,以使用上面定义的分析器。
@Field(index=Index.YES, store=Store.NO)
@Analyzer(definition = "customAnalyzer")
您需要重新索引或重新插入实体,才能使分析仪生效。
答案 2 :(得分:1)
如果你想搜索重音字符并在结果中找到相同的普通关键字,那么你必须在分析器中实现ASCIIFoldingFilterFactory类
local server
@Analyzer(definition =“customAnalyzer”)适用于实体或字段