Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

Другие советы

Я не знаю, поддерживают ли это реализации GAE JDO и JPA, но, используя низкоуровневый API, вы можете использовать operator 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
}

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

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

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

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

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

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

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

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

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

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

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

TL

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

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

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

TL

Одним из способов упростить необходимость "делать это самостоятельно" может быть использование параметризованных запросов:

   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));
   }

Вопреки ответу клетуса, ОР-ганизационные работы, во всяком случае, в более поздней версии App Engine.

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

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

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

Обновите App Engine до версии 1.3.4, и приложение заработает! Хотя и с ограничением.

В любом случае, спасибо клетусу:)

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

String filters = "( :values.contains(field) )";
Query query = pm.newQuery(myType.class, filters);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top