Lucene: как остановить поиск в текущем документе после первого совпадения - PullRequest
0 голосов
/ 06 января 2012

Название может быть несколько двусмысленным, но потерпите меня (Единственный похожий вопрос, который я мог найти, был Solr: Поиск в нескольких полях, НО ОСТАНОВИТЬ, если найдено совпадение документов , но это не помогло).У меня есть следующая структура для моих документов lucene:

FieldA (Store.YES, Index.ANALYZED), primary identification of an entity
FieldB (Store.YES, Index.ANALYZED), secondary identification(s) of an entity

FieldA может, например, содержать строку типа car, где FieldB может содержать строки типа automobile, vehicle и т. Д.. В документе может быть несколько полей FieldB.Анализатор индекса - StandardAnalyzer, анализатор поиска - KeywordAnalyzer (который, казалось, дал лучший результат, не уверен, что это лучший подход).Идентификатор в FieldA важнее идентификатора (ов) в FieldB.

Допустим, индекс содержит 3 документа (с полями FieldA | FieldB):

"car"       | "vehicle" "automobile"
"car parts" | "parts, car"
"car shop"  | "shop, car"

Все идет нормально.Теперь, где проблема заключается:

При запросе "car", я хотел бы увидеть следующий результат (оценки составлены):

car, score 1.0
car parts, score 0.9
car shop, score 0.9

Документ с FieldAзначение «car» должно отображаться первым, так как FieldA считается более важным, и запрос лучше всего соответствует этому значению.На самом деле происходит следующее:

car parts, score 0.625
car shop, score 0.625
car, score 0.5073969

searcher.explain() выводит следующее: (пропущено объяснение «автомастерская», поскольку оно совпадает с «автомобильными деталями»)

Explain: 0.625 = (MATCH) max of:
  0.31712303 = (MATCH) weight(fielda:car in 0), product of:
    0.71231794 = queryWeight(fielda:car), product of:
      0.71231794 = idf(docFreq=3, maxDocs=3)
      1.0 = queryNorm
    0.4451987 = (MATCH) fieldWeight(fielda:car in 0), product of:
      1.0 = tf(termFreq(fielda:car)=1)
      0.71231794 = idf(docFreq=3, maxDocs=3)
      0.625 = fieldNorm(field=fielda, doc=0)
  0.625 = (MATCH) fieldWeight(fieldb:car in 0), product of:
    1.0 = tf(termFreq(fieldb:car)=1)
    1.0 = idf(docFreq=2, maxDocs=3)
    0.625 = fieldNorm(field=fieldb, doc=0)
Explain: 0.5073969 = (MATCH) max of:
  0.5073969 = (MATCH) weight(fielda:car in 0), product of:
    0.71231794 = queryWeight(fielda:car), product of:
      0.71231794 = idf(docFreq=3, maxDocs=3)
      1.0 = queryNorm
    0.71231794 = (MATCH) fieldWeight(fielda:car in 0), product of:
      1.0 = tf(termFreq(fielda:car)=1)
      0.71231794 = idf(docFreq=3, maxDocs=3)
      1.0 = fieldNorm(field=fielda, doc=0)

TL; DR: с двумя полями повышение FieldA не поможет, потому что все 3 документа будут увеличены.Как получить lucene для ранжирования ближайшего совпадения (в данном примере «car») как наивысшего? Т.е. как остановить поиск в текущем документе после того, как (более важное) совпадение в FieldA будет найдено?

Ответы [ 2 ]

0 голосов
/ 10 марта 2012

Проблема в том, что в fieldb автомобиль встречается только в двух из трех терминов, тогда как в fielda автомобиль встречается во всех трех терминах.Таким образом, совпадение с автомобилем в полевых баллах выше, потому что у него более высокое значение idf (1,0 по сравнению с 0,7123174)

Значение совпадения по существу равно:

idf * idf * fieldnorm *tf

, где fieldnorm равен

lengthnorm * fieldboost

, поэтому вы можете видеть, что idf очень важен.

На самом деле, если бы вы увеличили поле a, это сработало бы, потому что совпадениядля поля a будет значение по сравнению с совпадениями для fieldb, и в вашем примере это совпадение для fieldb с более высоким рейтингом.

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

Использовать синтаксис NOT.

a:car^2 (+b:car -a:car)

Таким образом, значения, соответствующие совпадениям в b, будут игнорироваться, если они не соответствуют a.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...