Запрос Lucene не выполняется со смешанным MUST/MUST_NOT
Дан документ с этим текстом, проиндексированный в поле с именем Content:
The dish ran away with the spoon.
Следующий запрос не соответствует этому документу:
+Content:dish +(-Content:xyz) <-- no results!
Запрос должен обрабатываться как должен включать "блюдо", не должен включать "XYZ". Это "не должен" часть, которая терпит неудачу.
Я знаю, что комбинация + выглядит забавно, но синтаксически она должна быть правильной, особенно если учесть, что все следующие варианты работают:
+Content:dish +(-Content:xyz +Content:spoon) <-- this works
+Content:dish -Content:xyz <-- this works
Так почему не +(-Content:xyz)
Работа? Это по замыслу, или ошибка, или я просто что-то упустил? Я использую Lucene.Net, но я предполагаю, что обычный Lucene ведет себя так же.
1 ответ
Lucene не начинается с полного представления обо всем, как база данных SQL. Lucene начинается с того, что не найдено ни одного документа, и находит вещи на основе найденных предложений. Вот почему:
-Content:xyz
Сам по себе не работает. Он знает, что не нужно вводить контент:xyz, но ему не было предоставлено никаких документов для сравнения. То же самое относится и к вашему запросу, потому что он помещен в подзапрос.
-Content:xyz
оценивается первым, который не получает никаких документов самостоятельно. Итак, у вас есть, эффективно
+Content:dish +(no documents)
Это полезно думать о -
как AND NOT
а не просто NOT
(хотя не принимайте это, чтобы подразумевать, что синтаксис +/- и И / ИЛИ / НЕ обязательно отображается непосредственно друг на друга).
Если вы хотите иметь возможность выполнить такой одинокий отрицательный запрос, вам нужно сначала ввести все документы. MatchAllDocsQuery - лучший способ сделать это, например:
BooleanQuery query = new BooleanQuery();
query.add(new BooleanClause(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD));
query.add(new BooleanClause(new TermQuery(new Term("Content","xyz")), BooleanClause.Occur.MUST_NOT));
Будет эквивалентом запроса в стиле SQL с отрицанием только для предложения WHERE.
Конечно, это не обязательно в случае, который вы перечислили, так как:
+Content:dish -Content:xyz
Это совершенно адекватно.