Как выполнить поиск по дню рождения (не по дате рождения) в Solr?

У меня есть индекс, в котором хранятся даты рождения, и я хотел бы найти любого, чья дата рождения находится в пределах X дней от определенного месяца/дня. Например, я хотел бы знать, приближается ли чей-либо день рождения через определенное количество дней, независимо от того, в каком году они родились. Как бы я выполнил этот запрос с помощью Solr? (в поле "дата рождения")

В качестве продолжения, предполагая, что этот запрос выполняется очень часто, должен ли я индексировать что-то другое, кроме даты рождения? Например, просто пара месяц-день? Каков наиболее эффективный способ выполнения такого запроса (с точки зрения запроса и индексации)?


person Boom King    schedule 31.03.2009    source источник


Ответы (3)


Вы должны помнить, что Solr использует Lucene, и что на данный момент все хранится и индексируется как строка.

Запрос диапазона как есть не будет работать, потому что даты обычно внутренне индексируются как ГГГГММДД.

Наличие отдельного поля в индексе, в котором просто хранятся строки MMDD, было бы легко доступно для поиска. Или, если вам не нужно дополнительное поле и вы хотите индексировать даты по-другому, измените порядок при индексации, чтобы даты рождения были проиндексированы ММДДГГГ.

Затем вы можете создавать запросы диапазона, потому что все, с чем вам нужно сопоставляться, находится в начале строки, а lucene соответствует лексиографически.

(Запрос диапазона ba -> bc будет соответствовать BAt, BAseball, но не BEcause.)

Подобная индексация является единовременной фиксированной стоимостью и не разрушает ничего, кроме внутреннего расположения в хронологическом порядке. Если это проблема, используйте два поля, место на диске дешево!)

person Max    schedule 31.03.2009
comment
Хорошо, спасибо. Жаль, что ни у кого нет решения для выполнения этого поиска непосредственно в поле даты рождения ... Я возился с добавлением своего собственного FieldType для BirthdayField, который индексирует, как IntField, но запросы, как это DateField ... Много работы . - person Boom King; 01.04.2009
comment
Вероятно, есть способы поиска непосредственно в этом поле, но они неэффективны. В связи с этим вам потребуется много дополнительной логики, и вы не сможете получить полные ответы в одном запросе. - person Max; 01.04.2009
comment
Да, я действительно хотел получить ответ непосредственно на вопрос об этом поле, вместо этого все дали ответы на дополнительный вопрос, который я задал. И у меня уже было решение для продолжения (в соответствии с тем, что вы предложили). - person Boom King; 01.04.2009
comment
Solr предлагает функциональные возможности даты помимо тех, которые предлагает только lucene, поэтому ваши заявления о формате даты вводят в заблуждение: lucene.apache.org/solr/api/org/apache/solr/schema/ Как бы то ни было, вы правы — самое простое решение — определенно хранить MMDD-тип нить. - person Frank Farmer; 03.04.2009

Если пара день/месяц каверзная (я не знаю, так это или нет), почему бы не добавить поле «их день рождения в 1980 году» (жили они тогда или нет). Затем вам просто нужно выполнить поиск по 1980 году. Это фактически пара день/месяц, но сохраненная в виде, который вы можете легко использовать.

Обратите внимание, что 1980 год — високосный, поэтому я и выбрал его — иначе было бы трудно представить тех, у кого день рождения 29 февраля.

Альтернативно, пара «день/месяц» в виде целого числа:

(100 * month) + day

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

EDIT: У меня есть другая идея. Немного душновато, но даже так...

Сохраните дату рождения в формате, который фактически представляет собой месяц, день, год. Я не знаю, может ли Solr легко сделать это в формате MM/dd/yyyy, а затем выполнить поиск по лексикографическому порядку, но альтернативой является

(100000 * month) + (1000 * dayOfMonth) + (year - 1900)

(Предполагается, что вам не нужно хранить даты рождения ранее 1900 года. Я уверен, что вы можете настроить его.)

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

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

В любом случае, как я уже сказал, это немного необычно, но это может помочь :)

person Jon Skeet    schedule 31.03.2009
comment
Пара день/месяц — это не сложно, это просто означает еще одно поле в схеме, которое должно присутствовать во всех записях. Это то, чего я пытаюсь избежать. Установка даты дня рождения в определенном году почти аналогична паре месяц/день, только у нее ПОСТОЯННЫЙ год (вместо отсутствия года). - person Boom King; 31.03.2009

Вы можете сохранить день рождения как число от 1 до 366. Затем выполните поиск по этому значению. Преимущество заключается в том, что вы можете довольно легко искать диапазоны дней. Недостатком является то, что вы не можете легко использовать это поле для поиска людей, день рождения которых в этом месяце.

person Mr. Shiny and New 安宇    schedule 31.03.2009