1

用于分面搜索的 Apache Solr API 非常直观。使用 SolrQuery 类,可以轻松构建 AND 级联查询、针对存储库执行主题和处理结果。作为一个非常好的功能,Solr 发送回一个带有 FacetField 列表的 queryResponse 对象,该列表提供了剩余构面的调整基数。

for ( FacetField facetField : queryResponse.getFacetFields() )
{
    logger.debug( facetField.getName() );
    for ( Count count : facetField.getValues() )
    {
        logger.debug( " " + count.getName() + "(" + count.getCount() + ")" );
    }
}

我的问题是:是否可以配置 Solr,使这些返回的基数反映结合正则形式 (CNF) 中的查询,换句话说,查询不同构面字段的 AND 连接和相同构面字段的 OR 连接?

至少在默认配置中,似乎queryResponse.getFacetFields()只有 AND 连接的查询是假设的。我想在queryResponse.getFacetFields()没有解决方法的情况下使用,并希望问题是配置问题。

为了更好地理解这里一个具有 Solr API 的真实和预期返回值的具体用例:假设一组 1000 个项目。每个项目可能有多个概念分配和集合模式。因此,项目文档的 solr 模式具有c概念和moc收集模式两个字段。为这些字段启用了分面搜索。

希望容易理解,这里是伪代码中的相关查询和结果集的基数。F(c:position)指具有指定概念位置F(moc:postal)的项目集合, 指具有指定收件方式的项目集合。Qi显示查询和结果集,|Qi|是它的基数。

Q1: F(c:position) 
    -> |Q1| = 252
Q2: F(moc:telefonic) 
    -> |Q2| = 393
Q3: F(moc:postal) 
    -> |Q3| = 464
Q4: F(c:position) AND F(moc:telefonic) 
    -> |Q4| = 14 + 10 = 24
Q5: F(c:position) AND F(moc:postal) 
    -> |Q5| = 33 + 10 = 43
Q6: F(c:position) AND F(moc:telefonic) AND F(moc:postal) 
    -> |Q6| = 10
Q7: F(c:position) AND F(moc:telefonic) AND NOT F(moc:postal) 
    -> |Q7| = 14
Q8: F(c:position) AND F(moc:postal) AND NOT F(moc:telefonic) 
    -> |Q8| = 33
Q9: F(c:position) AND (F(moc:telefonic) OR F(moc:postal)) 
    -> |Q9| = 14 + 10 + 33 = 57

下图显示了集合和子集的基数:

分面搜索的维恩图

现在我们开始一个特定的搜索:Q9 是感兴趣的查询。选择任何构面。分面显示预期值:Q1 为 252,Q2 为 393,Q3 为 464。用户选择构面c:position并将结果集的基数从 1000 减少到 252。底层查询是 Q1。返回的方面显示 24 个项目moc:telefonic和 43 个项目moc:postal。这些值表明选择这些方面之一会将结果集限制为 24 (= 14 + 10) 或 43 (= 33 + 10) 项。在第二步中,用户另外选择了 facet moc:postal。基础查询是 Q5。结果集的真实基数和预期基数相互对应,为 43。到目前为止一切顺利!

moc:telefonic给定具有前一个选择的 CNF 查询,您现在希望返回的方面的基数是多少?我预计有 14 个项目。如果我选择方面,moc:telefonic我的结果集将从 43 项增加到 57 项。不幸的是,Solr 显示了 10 项。如果所有方面都是 AND 连接的,这将是正确的。作为用户,我感到困惑,因为我的结果集有 57 个而不是 53 个项目。

// Q5: F(c:position) AND F(moc:postal) 
solrDocumentList = queryResponse.getResults();
assertEquals( 43, solrDocumentList.getNumFound() );
facetField = queryResponse.getFacetField( "moc" );
assertEquals( "telefonic", facetField.getValues().get( 0 ).getName() );

// test fails: returned value is 10
assertEquals( 14, facetField.getValues().get( 0 ).getCount() );
4

0 回答 0