Я надеялся реализовать простой, но эффективный текстовый поиск для App Engine, который мог бы использовать до тех пор, пока не будут выпущены официальные возможности текстового поиска для механизма приложений. Я вижу, что есть библиотеки, но всегда сложно установить что-то новое. Мне интересно, если это правильная стратегия:
1) Разбейте каждое свойство, которое должно быть доступно для поиска по тексту, на набор (список) текстовых фрагментов.
2) Сохранить запись с добавлением этих списков
3) При поиске просто используйте фильтры равенства в свойствах списка
Например, если у меня была запись:
{
firstName="Jon";
lastName="Doe";
}
Я мог бы сохранить свойство как это:
{
firstName="Jon";
lastName="Doe";
// not case sensative:
firstNameSearchable=["j","o", "n","jo","on","jon"];
lastNameSerachable=["D","o","e","do","oe","doe"];
}
Тогда для поиска я мог бы сделать это и ожидать, что он вернет вышеупомянутую запись:
//pseudo-code:
SELECT person
WHERE firstNameSearchable=="jo" AND
lastNameSearchable=="oe"
Так ли реализован текстовый поиск? Как вы удерживаете индекс от выхода из-под контроля, особенно если у вас есть параграф или что-то? Есть ли какая-то другая стратегия сжатия, которая обычно используется? Полагаю, если я просто хочу что-то простое, это может сработать, но приятно знать о проблемах, с которыми я могу столкнуться.
Обновление :::
Хорошо, так получается, что эта концепция, вероятно, законна. Это сообщение в блоге также относится к этому: http://googleappengine.blogspot.com/2010/04/making-your-app-searchable-using-self.html
Примечание: исходный код в сообщении блога выше не работает с текущей версией Lucene. Я установил старую версию (2.9.3) в качестве быстрого исправления, так как в любом случае Google должен в скором времени выпустить собственный текстовый поиск для движка приложения.
Решение, предложенное в ответе ниже, является хорошим быстрым решением, но из-за ограничений большой таблицы работает, только если вы запрашиваете одно поле, потому что вы можете использовать операторы неравенства только для одного свойства в запросе:
db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2", "abc", u"abc" + u"\ufffd")
Если вы хотите сделать запрос по нескольким свойствам, вы можете сохранить индексы для каждого свойства. В моем случае я использую это для некоторых функций автоматического предложения в небольших текстовых полях, а не для поиска совпадений слов и фраз в документе (для этого вы можете использовать приведенную выше реализацию блога). Оказывается, это довольно просто, и мне не нужна библиотека для этого. Кроме того, я ожидаю, что если кто-то ищет «Ларри», они начнут набирать «La ...», а не начинать с середины слова: «arry». Таким образом, если свойство предназначено для имени человека или чего-то подобного, индекс имеет только подстроки, начинающиеся с первой буквы, поэтому индекс для "Larry" будет просто {"l", "la", "lar", "larr "," Ларри "}
Я сделал что-то другое для данных, таких как номера телефонов, где вы можете искать их, начиная с начальной или средней цифры. В этом случае я просто сохранил весь набор подстрок, начиная со строк длины 3, поэтому номер телефона "123-456-7890" будет: {"123", "234", "345", .... . "123456789", "234567890", "1234567890"}, всего (10 * ((10 + 1) / 2)) - (10 + 9) = 41 индекс ... на самом деле то, что я сделал, было немного больше сложный, чтобы удалить некоторые маловероятно используемые подстроки, но вы поняли идею.
Тогда ваш запрос будет:
(Код псевдо)
ВЫБЕРИТЕ * от человека ГДЕ
firstNameSearchIndex == "lar"
phonenumberSearchIndex == "1234"
Механизм приложения работает так: если подстроки запроса соответствуют какой-либо из подстрок в свойстве, это считается как совпадение.