Как этот запрос на присоединение к Solr 4.0 может вернуть больше результатов, чем запрос *: *? - PullRequest
0 голосов
/ 18 января 2012

Я столкнулся с очень странным поведением, которое я считаю ошибкой, но я могу ошибаться или неправильно понимать документацию, поэтому я спрашиваю.

У меня есть индекс SOLR и я работаю с новыми функциямиверсия 4.0.

Это код, который я использую (я использую расширение PECL SOLR):

<code><?
$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)."
";?>

Код выше возвращает 38296 документов. Однако, если я раскомментирую строку #$query->setQuery("*:*");, так что запрос теперь *:* и эффективно соответствует каждому документу, я получу 21867 возвращенных документов - я думаю, что это правильное число.

Если вы хотите узнать немного больше о сценарии использования и о том, что стоит за этим, вы можете читать дальше, но это только справочная информация:

Я индексирую два типа документов, которые я различаю по значениюполя type:

  • средний - в моем случае это фильм (например, аватар, касабланка и т. д.)

  • product -Это предложения для фильмов, как DVD наmazon

Причина такого разделения состоит в том, что я хочу фильтровать / фасетные запросы, которые позволяют пользователю, например, искать:

  • фильм, который былвыпущено в период между 1990 и 1955 годами (эти метаданные хранятся в промежуточном документе)
  • и доступно на amazon как DVD на 5% или менее (эта информация хранится в документе продукта)
  • и это имеет слово «джунгли» в названии фильма (хранится в документе носителя)

Я делаю поиск (используя dismax) по всем документам типа «средний» с «джунглями» взаголовок:

$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, которое содержит идентификатор документа связанного с ними носителя типа.

Это все работает отлично!Тем не менее, я хочу, чтобы поиск по метаде проводился в документах типа product.Например, страна, где они доступны (где я могу заказать DVD)

Я получаю подсчет фасетов для всех полей, которые содержатся в средних документах из этой очереди, однако запросы на соединение не содержат никакой информации оисходные таблицы, используемые для фильтрации объединения с результатом.Поэтому мне нужен второй запрос:

Я делаю то же самое, что и выше, но на этот раз я использую запросы на своп-соединение, а не соединенные:

Так что мой запрос dismax теперь становится запросом на соединение:

$ query-> setQuery ("{! Join from = id to = med_id} {! Type = dismax qf = '$ qf' mm = '1' q.alt = ': '} jungle ");

Мои присоединенные запросы фильтра становятся обычными запросами фильтра:

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

А мой обычный запрос фильтра становится объединенным - на этот раз от идентификатора поля до med_id:

$ query-> addFilterQuery ("! Join from = id to = med_id} release_year: [1990 - 1995]");

Теперь возвращаются все продукты, соответствующие нашим фильтрам.Для одного носителя может быть более одного продукта - но я хочу, чтобы количество моих аспектов отражало количество фильмов, а не количество продуктов, поэтому я также группирую по med_id и устанавливаю усечение для группы в значение true так:

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

Единственная проблема с этим состоит в том, что запрос на соединение, выполняющий поиск в средних полях, заставляет мой запрос каким-то образом возвращать больше результатов, а не меньше, что я свел к минимальному коду в начале вопроса для воспроизведения.

1 Ответ

0 голосов
/ 18 января 2012

Я думаю, что обошел проблему, добавив свой запрос как фильтр, а не как запрос:

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

Кажется, он работает в небольших тестовых случаях, однако у меня все еще есть некоторые неудачи вмои данные, но мне нужно дважды проверить источники данных на наличие опасностей и создать тестовый пример, в котором я смогу доказать разницу.

Мне также все еще интересно, почему возникают проблемы при установке в качестве запроса ...

Редактировать:

Метод, описанный в этом ответе, эффективно решает проблему, однако я не уверен, почему она вообще существовала.

Однако эффект фасетаcount не является желаемым, поскольку свертывание полей позволяет запрашивать фасет только для наиболее релевантного документа в группе.Значение: без свертывания (группировки) счет может быть больше, чем фактический счетчик сред (потому что может существовать несколько совпадающих продуктов).При свертывании может быть меньше (потому что учитываются только значения одного документа).Таким образом, количество аспектов не будет работать таким образом.Единственное, что вы действительно знаете, какие значения фасетов будут возвращать как минимум 1 результат, и в зависимости от того, используете ли вы свертывание или нет, число, представляющее верхнюю и нижнюю границу, но не фактическое число результатов.

...