API облачного хранилища данных — php — GqlQuery — SELECT * FROM kind_name WHERE __key__

У меня есть приложение в среде выполнения GAE:php, и я использую Google Cloud Datastore API для подключения к хранилищу данных из моего приложения PHP.

Мой вопрос:

Как я могу запросить мою базу данных с помощью ключей, что-то похожее на "SELECT * FROM table_name WHERE id <= 1410611039" в Sql.

Мой код: (я видел, что люди используют этот синтаксис строки запроса, и он работает для них)

$gql_query = new Google_Service_Datastore_GqlQuery();
$gql_query->setQueryString("SELECT * FROM notification WHERE __key__ = KEY('notification', 1410611039)");

Некоторая часть ошибки, которую я получаю, это Fatal error: Uncaught exception ... (400) Disallowed literal: KEY...

Представление консоли моего хранилища данных: введите здесь описание изображения

Все в порядке, пока я не добавляю WHERE __key__ = KEY('notification', 1410611039) к query_string.


person Behnam Rasooli    schedule 13.09.2014    source источник
comment
Cloud Datastore GQL немного отличается от App Engine GQL. Однако я не уверен в точной проблеме: вы пробовали notification без кавычек?   -  person Daniel Roseman    schedule 13.09.2014
comment
Да, я только что попробовал notification без кавычек, но все равно та же ошибка. К сожалению, для Datastore API нет руководства по созданию Gql-строки. Я думаю, что KEY('kind', 'name/id') — это метод создания ключа хранилища данных, но он не работает через API.   -  person Behnam Rasooli    schedule 14.09.2014


Ответы (2)


Ключи считаются литералами в Cloud Datastore GQL и требуют специальной обработки.

Если пользователи будут предоставлять значения во время выполнения, мы рекомендуем использовать привязку аргументов. Это помогает предотвратить злонамеренное поведение, такое как атаки путем внедрения.

Есть два способа сделать это; оба начинаются со значения ключа:

$key_path_element = new Google_Service_Datastore_KeyPathElement();
$key_path_element->setKind('notification');
$key_path_element->setId(1410611039);

$key = new Google_Service_Datastore_Key();
$key.setPath([$key_path_element]);

$key_value = new Google_Service_Datastore_Value();
$key_value->setKeyValue($key);

Затем $key_value можно использовать как именованный аргумент:

$gql_query = new Google_Service_Datastore_GqlQuery();
$gql_query->setQueryString("SELECT * FROM notification WHERE __key__ = $theKey");

$name_arg = new Google_Service_Datastore_GqlQueryArg();
$name_arg->setName("theKey");
$name_arg->setValue($key_value);

$gql_query->setNameArgs([$name_arg]);

или как позиционный аргумент:

$gql_query = new Google_Service_Datastore_GqlQuery();
$gql_query->setQueryString("SELECT * FROM notification WHERE __key__ = @1");

$number_arg = new Google_Service_Datastore_GqlQueryArg();
$number_arg->setValue($key_value);

$gql_query->setNumberArgs([$number_arg]);

Если в запрос не добавляется пользовательский ввод, другим вариантом является явное разрешение литералов в запросе:

$gql_query = new Google_Service_Datastore_GqlQuery();
$gql_query->setQueryString("SELECT * FROM notification WHERE __key__ = KEY('notification', 1410611039)");
$gql_query->setAllowLiteral(true);

Вот некоторые дополнительные сведения о привязке аргументов, а также полный справочник по GQL.

person Ed Davisson    schedule 15.09.2014
comment
Спасибо за чистое объяснение. Итак, мне не хватало $gql_query->setAllowLiteral(true);. Моя проблема заключалась в том, что я не знал, что ключи считаются литералами, и, честно говоря, я до сих пор не знаю, что это значит, из-за моего уровня английского! Было бы здорово, если бы кто-нибудь мог дать мне ключ. - person Behnam Rasooli; 16.09.2014

У меня была такая же проблема с использованием API хранилища данных Java. Решение на Java будет выглядеть так:

datastore = DatastoreOptions.builder()
.authCredentials(AuthCredentials.createApplicationDefaults())
.build()
.service();
String id = "asdf123";
Query<Entity> query = Query.gqlQueryBuilder(
    Query.ResultType.ENTITY, 
    "SELECT * FROM Task WHERE id = '"+id+"'")
    .allowLiteral(true)
    .build();
QueryResults<Entity> result = datastore.run(query);
while(result.hasNext()){
    Entity temp = result.next();
    //(...)
}
person ghorkov    schedule 11.03.2016