gpt4 book ai didi

java - 对来自 Lucene 索引的结果进行分类

转载 作者:太空宇宙 更新时间:2023-11-04 11:05:29 25 4
gpt4 key购买 nike

我有一个 Lucene 索引,它是在 Hibernate Search 注释的帮助下通过 Hibernate 生成的,其中包含 3 个描述文章的字段(只是为了简化一点):

id、标题、品牌

内容示例:

id、标题、品牌
1、《长裙》、《Sweet and Gabbana》
2、“甜领背心”、“阿玛尼”
3、“甜感衬衫”、“阿玛尼”

请注意“Sweet and Gabbana”、“甜领背心”和“甜感衬衫”如何共享“甜”这个词。

我想做一个 Lucene 查询,这样,如果我搜索关键字“sweet”,我会得到 2 个不同的类别,一个用于标题,另一个用于品牌。例如:

  • 标题 -> “甜领背心”、“甜感衬衫”
  • 品牌 ->“Sweet and Gabbana”

换句话说,我想向用户展示系统在这两个不同类别中找到了结果。

当我运行查询(标题和品牌之间的一种 OR)时,我得到了仅包含一个属性或另一个属性的所有三个条目(在 Lucene 中,id 为 1、2 和 3 的文档),但如何对它们进行分类?

@PersistenceContext
private EntityManager em;

...

@Override
public List<ArticleByIndexModel> retrieveArticlesSearchQueryResult(final String searchString,
final String languageIso639) {

final FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
final org.apache.lucene.search.Query luceneQuery = buildUpArticlesSearchLuceneQuery(searchString,
languageIso639, fullTextEntityManager);

final String titleFieldName = ArticleTranslationFieldPrefixes.TITLE + languageIso639;
final String brandNameFieldName = BrandTaxonomy.BrandTaxonomyNameFieldName.NAME;

final FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(luceneQuery);
fullTextQuery.setMaxResults(50);
fullTextQuery.setProjection(Article_.articleID.getName(), titleFieldName, brandNameFieldName,
Article_.brandSku.getName(), FullTextQuery.DOCUMENT_ID, FullTextQuery.EXPLANATION, FullTextQuery.THIS);

@SuppressWarnings("unchecked")
final List<Object[]> list = (List<Object[]>) fullTextQuery.getResultList();

final List<ArticleByIndexModel> resultList = list.stream()
.map(x -> new ArticleByIndexModel((Integer) x[0], (String) x[1])).collect(Collectors.toList());
return resultList;
}

private org.apache.lucene.search.Query buildUpArticlesSearchLuceneQuery(final String searchString,
final String languageIso639, final FullTextEntityManager fullTextEntityManager) {

final String brandSkuName = Article_.brandSku.getName();

final String analyzerPartName = ArticleTranslationDiscriminator.getAnalyzerPartNameByLanguage(languageIso639);
final String titleFieldName = ArticleTranslationFieldPrefixes.TITLE + languageIso639;
final String titleEdgeNGramFieldName = ArticleTranslationFieldPrefixes.TITLE_EDGE_N_GRAM + languageIso639;
final String titleNGramFieldName = ArticleTranslationFieldPrefixes.TITLE_N_GRAM + languageIso639;

final String brandNameEdgeNGramFieldName = BrandTaxonomy.BrandTaxonomyNameFieldName.NAME_EDGE_N_GRAM;
final String brandNameNGramFieldName = BrandTaxonomy.BrandTaxonomyNameFieldName.NAME_N_GRAM;

final SearchFactory searchFactory = fullTextEntityManager.getSearchFactory();
final QueryBuilder qb = searchFactory.buildQueryBuilder().forEntity(Article.class)
.overridesForField(titleFieldName, ArticleTranslationFieldPrefixes.TITLE + analyzerPartName)
.overridesForField(titleEdgeNGramFieldName,
ArticleTranslationFieldPrefixes.TITLE_EDGE_N_GRAM + analyzerPartName)
.overridesForField(titleNGramFieldName, ArticleTranslationFieldPrefixes.TITLE_N_GRAM + analyzerPartName)
.get();

final org.apache.lucene.search.Query luceneQuery =
/**/
qb.bool()
/**/
.should(qb.phrase().withSlop(2).onField(titleNGramFieldName).andField(titleEdgeNGramFieldName)
.boostedTo(5).sentence(searchString.toLowerCase()).createQuery())
/**/
.should(qb.phrase().withSlop(2).onField(brandNameNGramFieldName)
.andField(brandNameEdgeNGramFieldName).boostedTo(5).sentence(searchString.toLowerCase())
.createQuery())
/**/
.should(qb.keyword().onField(brandSkuName).matching(searchString.toLowerCase()).createQuery())
/**/
.createQuery();

return luceneQuery;
}

我没有看到进行 2 个不同查询然后合并结果的解决方案。

我读到了有关 Facets 的内容,但我认为它们不适合这种情况。

你有什么想法吗?

谢谢!!!

最佳答案

我假设您需要将结果作为单个列表向用户显示,其中包含每个项目的一些描述(因标题而匹配/因品牌而匹配/两者)。

我认为没有一个功能可以让您在 Hibernate Search 中完全执行此操作。我想有一些方法可以使用低级 Lucene API(收集器)来做到这一点,但这会涉及一些黑魔法,我认为我们无法将其插入 Hibernate Search。

所以,让我们走更简单的路:自己动手。

就我个人而言,我会简单地运行多个查询:

  • 第一次就像您在示例中所做的那样
  • 第二次投影 ID ( .setProjection(ProjectionContants.ID) ) 并仅使用两个子句:一个要求匹配的 ID 与第一个查询的结果之一具有相同的 ID(基本上是 must(should(id=<firstID>), should(id=<secondID>), ... ) ,另一个要求搜索字符串与标题匹配(基本上是 must(title=<searchString>)
  • 第三次与第二次类似,但用的是品牌而不是标题

然后,我将使用第二个和第三个查询的结果来确定给定结果是否因标题或品牌而匹配。

当然,只有当搜索字符串仅期望与标题或品牌(或两者)完全匹配时,这才有效,而当搜索字符串的某些部分与标题匹配,而其他部分与品牌匹配时,则无效。但如果这就是您想要的,那么您当前的查询无论如何都是错误的......

关于java - 对来自 Lucene 索引的结果进行分类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46521020/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com