Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

I've been using the php-gds library as a way of connecting my app to the GAE Cloud Datastore for quite some time and until recently I didn't require pagination because I simply didn't have enough data, well that has changed and I needed to implement this feature. I knew that to get pagination working I had to have an efficient way of getting a count of all of the entities of the same kind - this wasn't possible with standard php-gds functions and certainly wasn't supported via GQL. But there must have been a way.

Sure, I could fetch all entities and count how many there were, but this was the most expensive and least efficient way of going about it, so it wasn't even an option.

I had some pretty wild ideas about how this could be achieved efficiently - including keeping track of how many entities of the same kind were created and looking that up as needed. Turned out that was exactly what Google was doing already! ...with the NDB Administration queries.

It was possible to issue a standard GQL query like 'select * from __Stat_Kind__' and get all sorts of statistics on entity kinds, including the total count!
pagination1.png


So I figured that since this was looking up what appeared to as a standard entity in the Datastore, I could make this work with php-gds. So I put together some simple test code. Since the __Stat_Kind__ entity kind was using other entity kinds as key names, I could look up whatever entity kind I wanted stats for easily...
 PHP
$obj_store = new GDS\Store('__Stat_Kind__');
$obj = $obj_store->fetchByName('AG_GameEntity');
error_log(var_export($obj, true));


It gave me results!
 Output
GDS\Entity::__set_state(array(
'str_kind' => '__Stat_Kind__',
'str_key_id' => NULL,
'str_key_name' => 'AG_GameEntity',
'mix_ancestry' => NULL,
'arr_data' =>
array (
'builtin_index_bytes' => '232913',
'builtin_index_count' => '4910',
'bytes' => '308001',
'composite_index_bytes' => '17478',
'composite_index_count' => '100',
'count' => '100',
'entity_bytes' => '57610',
'kind_name' => 'AG_GameEntity',
'timestamp' =>
DateTime::__set_state(array(
'date' => '2018-04-14 00:25:25.000000',
'timezone_type' => 1,
'timezone' => '+00:00',
)),
),
'obj_schema' =>
GDS\Schema::__set_state(array(
'str_kind' => '__Stat_Kind__',
'arr_defined_properties' =>
array (
),
'str_entity_class' => '\\GDS\\Entity',
)),
))




I was on the right track and I could get the total count of entities of the same kind with this query - all I had to do was get the value of the 'count' property from the returned entity. It was so simple!

From here it was a matter of writing code that used the fetchPage() function on the Store class and I was done. The actual pagination code after having the total count of entities was more or less trivial, so I won't cover that part here.

There was a small catch to testing this in the local dev server. Unlike the production Datastore, the local Datastore does not automatically generate entity statistics. These needed to be generated manually via the dev server console.
pagination2.png


-i

A quick disclaimer...

Although I put in a great effort into researching all the topics I cover, mistakes can happen. Use of any information from my blog posts should be at own risk and I do not hold any liability towards any information misuse or damages caused by following any of my posts.

All content and opinions expressed on this Blog are my own and do not represent the opinions of my employer (Oracle). Use of any information contained in this blog post/article is subject to this disclaimer.
Hi! You can search my blog here ⤵
NOTE: (2022) This Blog is no longer maintained and I will not be answering any emails or comments.

I am now focusing on Atari Gamer.