Как реализовать Solr facet.missing = true с Lucene - PullRequest
0 голосов
/ 19 ноября 2018

Solr поддерживает возврат числа соответствующих документов без значения фасета для поля .Как этого можно добиться с помощью Lucene?

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

  • Документ 1 имеет category=A
  • Документ 2 имеет category=A и category=B
  • Документ 3 имеет category=B и category=C
  • Документ 4 и 5 не имеет значений category

Код выглядит как

 var facetsCollector = new FacetsCollector();
 FacetsCollector.Search(_indexSearcher, new MatchAllDocsQuery(), 100, facetsCollector);
 var state = DefaultSortedSetDocValuesReaderState(_indexReader, "category_facet");
 var facets = SortedSetDocValuesFacetCounts(state, facetsCollector);
 var children = facets.GetTopChildren(100, "category_dim");

Это дает мне LabelValues

  • Метка: A, Значение: 2
  • Метка: B, Значение: 2
  • Метка: C, Значение: 1

Как определить "Метка: (отсутствует), Значение: 2"?

Выполнение другого запроса +*:* -category:* - очевидный вариант.Однако можно ли сделать это умнее?

1 Ответ

0 голосов
/ 28 декабря 2018

Solr facet.missing функциональность выполняется без каких-либо сборщиков, просто сделав это:

SchemaField sf = searcher.getSchema().getField(fieldName);
DocSet hasVal = searcher.getDocSet(sf.getType().getRangeQuery(null, sf, null, null, false, false));
return docs.andNotSize(hasVal);

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

К сожалению, Lucene не имеет встроенной функциональности DocSet, поэтому потребуются некоторые хитрости. Я мог бы придумать что-то вроде этого:

Query q = some Lucene query
Set<Integer> queryRes = new HashSet<>();
searcher.search(q, new CheckHits.SetCollector(queryRes));

Set<Integer> missingRes = new HashSet<>();
searcher.search(new TermRangeQuery("category", null, null, false, false), new CheckHits.SetCollector(missingRes));
missingRes.retainAll(queryRes);

System.out.println(missingRes.size());

Функциональность сохранения HashSet должна быть довольно хорошей с точки зрения скорости. При необходимости этот коллектор может быть расширен для хранения идентификаторов где-то более эффективным способом

Полный пример можно найти там

...