2010-03-09 2 views
6

Каждый документ Lucene является рецептом, и каждый из этих рецептов содержит ингредиенты.Показатель Lucene с несколькими полями одинаковой природы

Im работает над тем, чтобы искать ингредиенты и давать результат, в котором говорится, что два ингредиента соответствуют четырем. (например)

Итак, как я могу добавить ингредиенты в документ? В solr я могу просто создать несколько полей, и это спасло бы их всех, я мог бы делать что-то неправильно, потому что это только сохранение одного ингредиента.

Также это применимо к полю типа «теги».

p.s Я использую Zend Framework для этого, если это имеет значение вообще.

ответ

12

Документы Lucene поддерживают добавление нескольких полей с тем же именем. то есть вы можете повторно позвонить:

document.add(new Field("name"), value) 

Так вы были сделать:

# (pseudo-code) 
document1.add(new Field("ingredient"), "vanilla") 
document1.add(new Field("ingredient"), "strawberry") 
index.add(document) 

# And then search for 
index.search("ingredient", "vanilla" && "strawberry") 

вы получите обратно Document1. Но если вы ищете:

index.search("ingredient", "vanilla" && "apple") 

Вы не получите обратно документа1.

Если вы искали:

index.search("ingredient", "vanilla" || "apple") 

Вы также можете получить обратно документ1.

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

Также обратите внимание, что по умолчанию PositionIncrementGap для полей с тем же именем, которые добавлены в документ: 0.

Это означает, что если вы добавили:

document1.add(new Field("ingredient"), "chocolate") 
    document1.add(new Field("ingredient"), "orange") 

, то он будет рассматриваться как если бы это был один ингредиент под названием «шоколад оранжевый», которые могли бы соответствовать на:

index.search("ingredient", "chocolate orange") 

Вы можете избежать для этого установите значение для PositionIncrementGap> 1, которое даст:

0 совпадений:

index.search("ingredient", "chocolate orange") 

и 1 матч за:

index.search("ingredient", "chocolate" && "orange") 
0

Я вижу два возможных подхода здесь:

  1. Денормализовать данные - создать отдельный документ для каждого ингредиента в рецепте, давая все документы для рецепта общего рецепта ид. Затем, во время поиска, суммируйте все совпадения идентификатора рецепта. Немного уродливый.
  2. Объедините все свои ингредиенты в общее поле и укажите его как «Текст». Затем поиск ингредиентов с использованием логического запроса с помощью «OR» (это называется «нужно» в выражениях Java Lucene, я не знаю эквивалент PHP).

Предлагаю вам попробовать второй подход и посмотреть, поможет ли он.

Смежные вопросы