Hibernate 使用@ClassBridge 搜索多个字段
Hibernate Search multiple fields with @ClassBridge
首先祝大家新年快乐!
我想用多种语言索引实体标签。
我有 2 个实体:
我的实体
- 标签代码
翻译
- 代码
- 语言代码
- 标签
MyEntity.labelCode 必须与 Translation.code 匹配,然后每个 MyEntity 实例有多种语言的多个标签。
我在 MyEntity 上写了一个 ClassBridge 来向文档添加多个字段:
class I18NTranslationClassBridge implements FieldBridge {
Analyzer analyzer
@Override
void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
if (value && value instanceof I18NDictionaryCategory) {
I18NDictionaryCategory entity = value as I18NDictionaryCategory
String labelCode = entity.getLabelCode()
def translations = TranslationData.findAllByCode(labelCode)
if (!analyzer) analyzer = Search.getFullTextSession(Holders.getApplicationContext().sessionFactory.currentSession).getSearchFactory().getAnalyzer('wildcardAnalyzer')
translations?.each { translation ->
document.add(getStringField("labelCode_${translation.languageCode}", translation.label, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO, 1f, analyzer))
document.add(getStringField("labelCode__${translation.languageCode}_full", translation.label, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO, 1f, null))
}
}
}
private static Field getStringField(String fieldName, String fieldValue, Field.Store store, Field.Index index, Field.TermVector termVector, float boost, Analyzer analyzer) {
Field field = new Field(fieldName, fieldValue, store, index, termVector);
field.setBoost(boost);
// manually apply token stream from analyzer, as hibernate search does not
// apply the specified analyzer properly
if (analyzer) {
try {
field.setTokenStream(analyzer.reusableTokenStream(fieldName, new StringReader(fieldValue)));
}
catch (IOException e) {
e.printStackTrace();
}
}
return field
}
}
我想为每种语言索引 2 个字段:1 个没有分析器和分词器(用于排序结果),另一个有分词器(用于全文搜索)。
我的问题是所有没有分析器的字段都被很好地索引,但有分析器的字段却没有。只有 1 种语言被正确编入索引。
我尝试用 ClassBridge 或 FieldBridge 来做,但没有成功。
有什么建议吗?
此致,
里奥
您不应在 class/field 网桥中使用分析器。分析器在稍后阶段应用。 Hibernate Search 在所谓的 ScopedAnalyzer
中收集所有必需的分析器,当 Lucene Document
添加到索引时会使用它。为了支持您的用例,您可以使用动态分析器选择功能。另见 http://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#d0e4119。
基本方法是通过@AnalyzerDiscriminator
定义特定于语言的分析器。这使得它们可以通过名称在全球范围内使用。然后你需要实现org.hibernate.search.analyzer.Decriminator
。您基本上 return 正确的分析器名称取决于您的字段名称(假设字段名称以某种形式包含语言代码)。最后但同样重要的是你需要用 @AnalyzerDiscriminator(impl = MyDiscriminator.class)
.
注释 MyEntity
首先祝大家新年快乐!
我想用多种语言索引实体标签。
我有 2 个实体:
我的实体
- 标签代码
翻译
- 代码
- 语言代码
- 标签
MyEntity.labelCode 必须与 Translation.code 匹配,然后每个 MyEntity 实例有多种语言的多个标签。
我在 MyEntity 上写了一个 ClassBridge 来向文档添加多个字段:
class I18NTranslationClassBridge implements FieldBridge {
Analyzer analyzer
@Override
void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
if (value && value instanceof I18NDictionaryCategory) {
I18NDictionaryCategory entity = value as I18NDictionaryCategory
String labelCode = entity.getLabelCode()
def translations = TranslationData.findAllByCode(labelCode)
if (!analyzer) analyzer = Search.getFullTextSession(Holders.getApplicationContext().sessionFactory.currentSession).getSearchFactory().getAnalyzer('wildcardAnalyzer')
translations?.each { translation ->
document.add(getStringField("labelCode_${translation.languageCode}", translation.label, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO, 1f, analyzer))
document.add(getStringField("labelCode__${translation.languageCode}_full", translation.label, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO, 1f, null))
}
}
}
private static Field getStringField(String fieldName, String fieldValue, Field.Store store, Field.Index index, Field.TermVector termVector, float boost, Analyzer analyzer) {
Field field = new Field(fieldName, fieldValue, store, index, termVector);
field.setBoost(boost);
// manually apply token stream from analyzer, as hibernate search does not
// apply the specified analyzer properly
if (analyzer) {
try {
field.setTokenStream(analyzer.reusableTokenStream(fieldName, new StringReader(fieldValue)));
}
catch (IOException e) {
e.printStackTrace();
}
}
return field
}
}
我想为每种语言索引 2 个字段:1 个没有分析器和分词器(用于排序结果),另一个有分词器(用于全文搜索)。
我的问题是所有没有分析器的字段都被很好地索引,但有分析器的字段却没有。只有 1 种语言被正确编入索引。
我尝试用 ClassBridge 或 FieldBridge 来做,但没有成功。
有什么建议吗?
此致,
里奥
您不应在 class/field 网桥中使用分析器。分析器在稍后阶段应用。 Hibernate Search 在所谓的 ScopedAnalyzer
中收集所有必需的分析器,当 Lucene Document
添加到索引时会使用它。为了支持您的用例,您可以使用动态分析器选择功能。另见 http://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#d0e4119。
基本方法是通过@AnalyzerDiscriminator
定义特定于语言的分析器。这使得它们可以通过名称在全球范围内使用。然后你需要实现org.hibernate.search.analyzer.Decriminator
。您基本上 return 正确的分析器名称取决于您的字段名称(假设字段名称以某种形式包含语言代码)。最后但同样重要的是你需要用 @AnalyzerDiscriminator(impl = MyDiscriminator.class)
.
MyEntity