这个solr 4.0连接查询如何返回比*:*查询更多的结果?

时间:2012-01-18 18:51:29

标签: join solr lucene faceted-search

我遇到了一些非常奇怪的行为,我认为这是一个错误,但我可能错了或者没有正确理解文档,所以我要问。

我有一个SOLR索引并使用4.0版本的新功能。

这是我使用的代码(我正在使用PECL SOLR扩展名):

<?
$options = array (
    'hostname' => '192.168.200.31',
    'path' => 'solr/slave',
);
$client = new SolrClient($options);
$query = new SolrQuery();

#$query->setQuery("{!join from=id to=med_id }type:medium");
$query->setQuery("*:*");

$query->addFilterQuery('type:product');
$query->addFilterQuery("product_type:tv_free");
$query_response = $client->query($query);
$response = $query_response->getResponse();
echo '<pre>'.print_r($response,true)."</pre>";
?>

上面的代码返回38296个文档。 但是,如果我取消注释行#$query->setQuery("*:*");,以便查询现在为*:*并且有效地匹配每个文档,我会返回21867个文档 - 我认为这是正确的数字。

如果您想进一步了解用例以及背后的想法,可以继续阅读 - 但这只是背景信息:

我正在使用字段type的值来区分两种类型的文档:

  • medium - 就我而言,这是一部电影(如头像,卡萨布兰卡等)

  • 产品 - 这些是电影的提供,如亚马逊的DVD

这种拆分的原因是我想要过滤器/方面查询,以便用户例如搜索:

  • 1990年至1955年间发行的电影(此元数据存储在媒体文件中)
  • 并且在亚马逊上可以获得5%或更低的dvd(此信息存储在产品文档中)
  • 在电影片名中有“丛林”字样(存储在媒体文件中)

我正在搜索(使用dismax)所有类型为“medium”的文档,标题为“jungle”:

$query->setQuery("{!type=dismax qf='$qf' mm='1' q.alt='*:*'}jungle");

然后我添加一个像这样的过滤器查询:

$query->addFilterQuery("{!join from=med_id to=id}provider:amazon");
$query->addFilterQuery("{!join from=med_id to=id}price:[0 TO 500]"); // price is in cents
$query->addFilterQuery("release_year:[1990 TO 1995]"); 

请注意,我需要前两个查询作为prdouct类型文档的连接,它包含一个名为med_id的字段,该字段包含与它们关联的类型为media的文档的id。

一切正常! 我想要在产品类型的文件中进行的metada搜索。例如,他们可以使用的国家(我可以订购DVD)

我从此quere获取介质文档中包含的所有字段的facet计数,但是join连接查询不携带用于过滤连接到结果的源表的任何信息。所以我需要第二个查询:

我做的与上面完全一样,但这次我使用交换连接而不是连接查询:

所以我的dismax查询现在变成了一个连接查询:

$ query-&gt; setQuery(“{!from from = id to = med_id} {!type = dismax qf ='$ qf'mm ='1'q.alt =' “}丛林“);

我加入的过滤器查询变为普通过滤器查询:

$query->addFilterQuery("provider:amazon");
$query->addFilterQuery("price:[0 TO 500]"); 

我的传统过滤器查询变成了一个加入的 - 这次是从字段id到med_id:

$ query-&gt; addFilterQuery(“!from from = id to = med_id} release_year:[1990 to 1995]”);

现在返回与我们的过滤器匹配的所有产品。对于一种媒体,可能有不止一种产品 - 但我只希望我的方面数量反映电影数量,而不是产品数量,所以我也按照med_id进行分组,并将组截断设置为真如下:

$query->addParam("group","true");
$query->addParam("group.field","med_id");
$query->addParam("group.truncate","true");

唯一的问题是在媒体字段中进行搜索的连接查询使得我的查询以某种方式返回更多结果而不是更少,我将其归结为问题开头的最小代码以重现。

1 个答案:

答案 0 :(得分:0)

我认为我通过将查询添加为过滤查询而不是像这样的查询来解决我的问题:

$query->addFilterQuery("{!join from=id to=med_id }{!type=dismax qf='$qf' mm='1' q.alt='*:*'}".$qs);
$query->setQuery("*:*");

它似乎适用于小型测试用例但是我的数据库仍然存在一些不适应但我需要仔细检查我的数据源是否有任何危险,并设置一个测试用例,我可以证明其差异。

我仍然感兴趣为什么在设置为查询时会出现问题......

编辑:

本回答中描述的方法有效地解决了这个问题,但是我不确定它为什么会存在。

然而,构面计数的效果不是所需的,因为字段折叠使solr facet仅适用于组中最相关的文档。 含义: 在没有折叠(分组)的情况下,计数可能大于介质的实际结果计数(因为可能存在多个匹配的产品)。 折叠可能会更少(因为只考虑一个文档的值)。 因此,方面计数不会以这种方式运作。你真正知道哪个方面值至少会返回1个结果,这取决于你是使用折叠还是不是表示上限和下限但可能不是实际结果数的数字。