Как создать автозаполнение с помощью GAE? - PullRequest
3 голосов
/ 17 октября 2011

Я использую jQuery UI виджет автозаполнения .Также у меня есть хранилище данных GAE:

class Person(db.Model):
    # key_name contains person id in format 'lastname-firstname-middlename-counter',
    # counter and leading dash are omitted, if counter=0
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    middle_name = db.StringProperty()

Как я могу найти человека в виджете автозаполнения, когда пользователь может ввести там фамилию, имя и / или отчество?

Итак, яполучаю пользовательскую строку ввода как self.request.get('term').Как мне искать то же самое в моем хранилище данных (так как мне нужно просмотреть каждое поле и, возможно, объединенное значение из 3 полей)?Как оптимизировать такой запрос?Мне также не ясно, каким должен быть формат ответа.Документ jQuery говорит:

Источник данных может быть:

an Array with local data
a String, specifying a URL
a Callback

Локальные данные могут быть простым массивом строк или содержать объекты для каждого элемента в массиве,со свойством label или value или обоими.

Ответы [ 2 ]

6 голосов
/ 17 октября 2011

Здесь есть несколько хитрых трюков.Рассмотрим эту расширенную модель:

class Person(db.Model):
  first_name = db.StringProperty()
  last_name = db.StringProperty()
  middle_name = db.StringProperty()
  names_lower = db.StringListProperty()

Вам нужно будет синхронизировать names_lower с реальными полями, например:

p.names_lower = [p.first_name.lower(), p.last_name.lower(),
                 p.middle_name.lower()]

Вы можете сделать это более элегантно с помощью DerivedProperty .

И теперь ваш запрос:

term = self.request.get('term').lower()
query = Person.all()
query.filter('names_lower >=', term)
query.filter('names_lower <=', unicode(term) + u"\ufffd")

Это дает вам:

  • Соответствие по всем 3 свойствам с одним индексом
  • Совпадения без учета регистра
  • Совпадения с подстановочным знаком

Таким образом, запрос «smi» вернет любого человека с любым именем, начинающимся с «smi» в любом случае.

Копирование имен в нижнем регистре в ListProperty позволяет выполнять поиск без учета регистра и позволяет искать все 3 поля одним запросом.«\ ufffd» - это максимально возможный символ Юникода, поэтому это верхний предел для соответствия нашей подстроки.Если по какой-то причине вы хотите точное совпадение, вместо этого укажите 'names_lower =', term.

Редактировать :

Как мне искать то же самое в моем хранилище данных(так как мне нужно посмотреть на каждое поле и, возможно, для комбинированного значения 3 полей)?Как оптимизировать такой запрос?

Это уже учтено в исходном решении.Взяв 3 поля и скопировав их в один ListProperty, мы, по сути, создаем один индекс с несколькими записями на человека.Если у нас есть человек по имени Боб Дж. Смит, у него будет 3 попадания в нашем индексе:

  • names_lower = bob
  • names_lower = j
  • names_lower = smith

Это исключает необходимость выполнения отдельных запросов для каждого поля.

Мне также не ясно, каким должен быть формат ответа.

Внимательно прочитайте документы .Форматирование вывода для jQuery должно быть довольно простым.Ваш источник данных будет строкой, указывающей URL, и вы захотите отформатировать ответ как JSON.

1 голос
/ 22 октября 2011

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

Все сделано в GAE с Python и использованием YUI3 вместо jQuery (вместо этого было бы просто подключить jQuery или любую другую библиотеку).

Короче говоря, идея состоит в том, что хранилище данных содержит набор документов, которые индексируются с использованием ключевых слов (используя объект индексации отношений). И когда пользователь вводит слова для поиска, система автоматически заполняет их ключевыми словами из этих документов.

...