Хранилище данных App Engine не поддерживает оператор ИЛИ - PullRequest
3 голосов
/ 31 мая 2009

Я пытаюсь запросить в хранилище данных Google что-то вроде (с pm -> persistanceManager):

String filters = "(  field == 'value' ||  field == 'anotherValue' )";
Query query = pm.newQuery(myType.class, filters);

Когда я выполняю - я возвращаюсь: Хранилище данных App Engine не поддерживает оператор ИЛИ .

Каков наилучший подход для людей к таким запросам?

Любая помощь приветствуется!

Ответы [ 8 ]

10 голосов
/ 31 мая 2009

Выполнить несколько запросов. Хранилище данных, как и все другие базы данных, не может эффективно выполнять дизъюнкции. В отличие от других баз данных, это создает трудности для пользователя, чтобы понять, что то, что вы делаете, неэффективно. Ваше единственное решение - выполнить несколько запросов - по одному для каждого или - и объединить их.

4 голосов
/ 12 февраля 2010

Я не знаю, поддерживают ли это реализации GAE JDO и JPA, но используя низкоуровневый API, вы можете использовать оператор IN для этого в одном запросе.

Query query = new Query("Issue");
List<String> list = Arrays.asList("NEW", "OPEN", "ACCEPTED");
query.addFilter("status", FilterOperator.IN, list);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
PreparedQuery preparedQuery = datastore.prepare(query);
for (Entity entity : preparedQuery.asIterable()) {
    // should iterate over 'NEW', 'OPEN' and 'ACCEPTED' issues
}
2 голосов
/ 31 мая 2009

Согласно Google App Engine - Запросы и индексы :

Фильтры запросов

A filter указывает имя поля, оператор и значение. Значение должно быть предоставлено приложением; это не может обратиться к другой собственности, или быть рассчитывается с точки зрения других свойства. Оператор может быть любым из следующее: < <= == >= >

Примечание: Интерфейс хранилища данных Java не поддерживает! = И Фильтр IN операторы, которые реализованы в Интерфейс хранилища данных Python. (В Интерфейс Python, эти операторы реализовано на стороне клиента библиотеки как несколько хранилищ данных запросы; они не являются особенностями само хранилище данных.)

Тема фильтра может быть любой поле объекта, включая основной ключ и родительский объект группы лиц (см. Сделки ).

Сущность должна соответствовать всем фильтрам, чтобы быть результат. В синтаксисе строки JDOQL указано несколько фильтров разделены && (логические «и»). Другие логические комбинации фильтров (логическое «или», «не») не являются поддерживается.

Из-за способа, которым App Engine хранилище данных выполняет запросы, один запрос не может использовать фильтры неравенства (< <= >= >) на более чем одном имущество. Фильтры множественного неравенства на том же свойстве (например, запрос для диапазона значений). См. Ограничения для запросов .

По сути, вам либо придется реструктурировать ваши данные, чтобы вы могли найти то, что вы ищете, с одним условием или несколькими условиями "и", либо вам придется получать данные с помощью двух (или подробнее) запрашивает и фильтрует / объединяет его в своем коде.

1 голос
/ 09 июля 2009

Последние новости .. по крайней мере, я просто получаю это. Когда я загружал последний Java SDK для GAE, я заметил в Примечаниях к выпуску, что «Проблема 29: Expose batch get» была исправлена ​​в последней версии (v1.2.1). По сути, кажется, что у нас (я ищу ту же поддержку, что и кажется) может быть альтернатива на основе JDO, а не переходить на «низкоуровневый» API хранилища данных. Я только что скачал последнюю версию Java GAE SDK, поэтому у меня еще не было возможности что-либо протестировать, но я хотел дать вам быстрый ответ. Я опубликую все, что узнаю после того, как у меня будет возможность подтвердить это "исправление".

Пожалуйста, примите мои извинения, если я нарушил этикет StackOverflow, повторно опубликовав свой комментарий в качестве ответа, но я решил сделать это по двум причинам. Во-первых, потому что, хотя я снова решаю ту же проблему, ИМХО эта новая информация, по-видимому, дает совершенно другой «ответ» на проблему. И во-вторых, я был обеспокоен тем, что форма комментария может не привлечь ваше внимание, прежде чем вы потратите много времени на изучение первого ответа, который я предоставил.

В следующий раз я подумаю более внимательно, прежде чем действовать.

TL

1 голос
/ 07 июля 2009

Извините, что опоздал на игру ... Я только что натолкнулся на ваш вопрос сегодня.

Другой способ «имитировать» поведение «IN» и «OR» - использовать API «низкого уровня» Datastore API. DatastoreService поддерживает метод get (), который принимает коллекцию ключей и возвращает карту всех сущностей, которые соответствуют переданным в ключи. Это интерфейс, но есть удобный DatastoreServiceFactory, который выдаст готовый экземпляр.

К сожалению, Google решил, что они не хотят продвигать этот низкоуровневый подход к API, и предпочитает, чтобы разработчики использовали JDO или JPA, поэтому нет никакой доступной документации, кроме JavaDocs и любых примеров кода, которые вы можете найти, когда вы Google "DatastoreService".

TL

0 голосов
/ 22 июля 2015

Вы можете использовать метод содержимого

String filters = "( :values.contains(field) )";
Query query = pm.newQuery(myType.class, filters);
0 голосов
/ 11 июня 2010

Вопреки ответу Cletus, ИЛИ работает , в любом случае в более поздней версии App Engine.

Действительно, я обнаружил, что ИЛИ не работал в App Engine 1.3.0, который у меня был, но согласно Google App Engine - Запросы и индексы (тот же источник, о котором говорится в его ответе)

Сущность должна соответствовать всем фильтрам, чтобы быть результатом. В строковом синтаксисе JDOQL вы можете разделить несколько фильтров с помощью || (логическое «или») и && (логическое «и»), хотя имейте в виду, что || может использоваться только тогда, когда все фильтры, которые он разделяет, имеют одинаковое имя поля. Другими словами, || допустимо только в ситуациях, когда фильтры, которые он разделяет, могут быть объединены в один фильтр contains ().

Я понял, что с момента его ответа (и с тех пор, как я в последний раз обновлял свой App Engine), App Engine должен быть обновлен по этому вопросу.

Обновите App Engine до 1.3.4, и OR-ing работает! Хотя и с ограничением.

В любом случае, благодаря Cletus:)

0 голосов
/ 09 июня 2009

Один из способов упростить «сделай сам» - использовать параметризованные запросы:

   Query query = pm.newQuery(mytype.class);
   query.setFilter("field == autoParam");
   query.declareParameters("String autoParam");

   List<String> params = myListOfThingsFieldCanBeEqualTo;

   Set merged = new HashSet();
   for (String f : params) {
     merged.addAll(q.execute(f));
   }
...