Google App Engine: возможно ли выполнить запрос Gql LIKE?

Простой действительно. В SQL, если я хочу найти в текстовом поле пару символов, я могу сделать:

SELECT blah FROM blah WHERE blah LIKE '%text%'

В документации для App Engine не упоминается, как этого добиться, но, безусловно, это достаточно распространенная проблема?

12 ответов

Решение

BigTable, который является базой данных для App Engine, будет масштабироваться до миллионов записей. Из-за этого App Engine не позволит вам выполнить какой-либо запрос, который приведет к сканированию таблицы, так как производительность будет ужасной для хорошо заполненной таблицы.

Другими словами, каждый запрос должен использовать индекс. Вот почему вы можете сделать только =, > а также < запросы. (На самом деле вы также можете сделать != но API делает это, используя комбинацию > а также < запросы.) Именно поэтому среда разработки отслеживает все запросы, которые вы делаете, и автоматически добавляет недостающие индексы в ваш index.yaml файл.

Нет способа индексировать для LIKE запрос, поэтому он просто недоступен.

Посмотрите эту сессию Google IO, чтобы получить более подробное и подробное объяснение этого.

Я сталкиваюсь с той же проблемой, но я нашел что-то на страницах Google App Engine:

Совет: Фильтры запросов не имеют явного способа сопоставления только части строкового значения, но вы можете подделать совпадение префикса, используя фильтры неравенства:

db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2",
            "abc",
            u"abc" + u"\ufffd")

Это сопоставляет каждую сущность MyModel со свойством свойства string, которое начинается с символов abc. Строка Юникода u"\ufffd" представляет максимально возможный символ Юникода. Когда значения свойств сортируются в индексе, значения, попадающие в этот диапазон, являются всеми значениями, которые начинаются с данного префикса.

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html

может быть, это может сработать;)

Хотя App Engine не поддерживает LIKE-запросы, взгляните на свойства ListProperty и StringListProperty. Когда для этих свойств будет выполнен тест на равенство, он будет фактически применен ко всем элементам списка, например: list_property = value проверяет, появляется ли значение где-либо в списке.

Иногда эту функцию можно использовать как обходной путь к отсутствию LIKE-запросов. Например, он позволяет выполнять простой текстовый поиск, как описано в этом посте.

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

Gaelyk предоставляет предметно-ориентированный язык для более удобных поисковых запросов. Например, следующий фрагмент найдет первые десять книг, отсортированных из последних с заголовком, содержащим fernи жанр точно совпадает thriller:

def documents = search.search {
    select all from books
    sort desc by published, SearchApiLimits.MINIMUM_DATE_VALUE
    where title =~ 'fern'
    and genre =  'thriller'
    limit 10
}

Like написано как оператор поиска Groovy =~, Он поддерживает такие функции, как distance(geopoint(lat, lon), location) также.

Движок приложения запустил универсальную службу полнотекстового поиска в версии 1.7.0, которая поддерживает хранилище данных.

Подробности в объявлении.

Подробнее о том, как это использовать: https://cloud.google.com/appengine/training/fts_intro/lesson2

Посмотрите на Objectify здесь, это похоже на API доступа к хранилищу данных. Есть FAQ с этим вопросом конкретно, вот ответ

Как мне сделать подобный запрос (LIKE "foo%")
Вы можете сделать что-то вроде startWith или endWith, если вы измените порядок при сохранении и поиске. Вы делаете запрос диапазона с начальным значением, которое вы хотите, и значением чуть выше того, которое вы хотите.

String start = "foo";
    ... = ofy.query(MyEntity.class).filter("field >=", start).filter("field <", start + "\uFFFD");

В общем, даже если это старый пост, способ создать 'LIKE' или 'ILIKE' состоит в том, чтобы собрать все результаты из запроса '>=', а затем зациклить результаты в python (или Java) для элементов, содержащих то, что вы ищу.

Допустим, вы хотите фильтровать пользователей по заданному a q='luigi'

users = []
qry = self.user_model.query(ndb.OR(self.user_model.name >= q.lower(),self.user_model.email >= q.lower(),self.user_model.username >= q.lower()))

for _qry in qry:
 if q.lower() in _qry.name.lower() or q.lower() in _qry.email.lower() or q.lower() in _qry.username.lower():
      users.append(_qry)

Просто следуйте здесь: init.py # 354 "> http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/init.py # 354

Оно работает!

class Article(search.SearchableModel):
    text = db.TextProperty()
    ...

  article = Article(text=...)
  article.save()

To search the full text index, use the SearchableModel.all() method to get an
instance of SearchableModel.Query, which subclasses db.Query. Use its search()
method to provide a search query, in addition to any other filters or sort
orders, e.g.:

  query = article.all().search('a search query').filter(...).order(...)

Я проверил это с помощью низкоуровневого Java API GAE Datastore. У меня и работает отлично

    Query q = new Query(Directorio.class.getSimpleName());

    Filter filterNombreGreater = new FilterPredicate("nombre", FilterOperator.GREATER_THAN_OR_EQUAL, query);
    Filter filterNombreLess = new FilterPredicate("nombre", FilterOperator.LESS_THAN, query+"\uFFFD");
    Filter filterNombre =  CompositeFilterOperator.and(filterNombreGreater, filterNombreLess);

    q.setFilter(filter);

Невозможно выполнить LIKE-поиск в механизме приложения хранилища данных, однако создание Arraylist сработало бы, если вам нужно найти слово в строке.

@Index
    public ArrayList<String> searchName;

и затем искать в индексе, используя objectify.

List<Profiles> list1 = ofy().load().type(Profiles.class).filter("searchName =",search).list();

и это даст вам список всех предметов, которые содержат мир, который вы сделали в поиске

"Нравится" часто используется в качестве заменителя бедняков для текстового поиска. Для текстового поиска можно использовать Whoosh-AppEngine.

Если LIKE '%text%' всегда сравнивается со словом или несколькими (подумайте о перестановках), и ваши данные изменяются медленно (медленно означает, что создание и обновление индексов не слишком дорого - как по цене, так и по производительности), тогда может быть сущность Relation Index Entity (RIE) ответ.

Да, вам придется создать дополнительную сущность хранилища данных и заполнить ее соответствующим образом. Да, есть некоторые ограничения, с которыми вам придется поиграть (одно из них - ограничение в 5000 на длину свойства списка в хранилище данных GAE). Но результаты поиска молниеносны.

Для получения дополнительной информации см. Мой RIE с Java и Ojbectify и RIE с сообщениями Python.

Другие вопросы по тегам