Data Storage

Work with a non relational cloud database

Here you’ll learn

Collections, which can have different access permissions.

Entities, which are stored inside those collections following a MongoDB structure.

The API calls to operate your game’s Cloud Storage data.

Storing and retrieving cloud data for your game is one of the core features of Gamedonia. Here we will take a look at how to manage and organize your data. Let's start with some basic concepts:

Basic concepts

The Gamedonia Backend data storage is based in a NoSQL MongoDB database. Let's look at a couple of concepts to understand the basics of Gamedonia cloud storage.

Entities

This is the most atomic data in Gamedonia. An entity is a set of Key-value pairs which is stored in the backend in BSON format (Binary JSON). Gamedonia SDKs will help you with the conversion from native types to BSON format. Entities are grouped in collections, and each entity will exist only on a specific collection.

Collections

A Collection groups objects that represent the same concept. For instance, each entity in the collection called towns would represent a specific towns. This is a similar concept to the tables in SQL. Entities in the same collection don't need to be similar in composition, though usually they will share most of their attributes.

You can create collections at the Dashboard. There are two kinds of collections in Gamedonia.

  • Normal - Collections for dynamic data. You can set permission levels for this kind of collection.
    • Own Read - Users can see entities they created.

    • Own Write - Users can modify entities they created.

    • Others Read - Users can see entities other users created.

    • Others Write - Users can modify entities other users created.

  • Master - These collections will store static data, which will always be read-only and never modified by any user. An example of this kind of collection would store the complete list of items for a game, difficulty or other attributes for each level of the game, etc. All data inside a Master collection will be transferred when deploying from the Development enviroment to Live. You can learn more about this process at our Deployment guide.

Gamedonia calls will only work under a valid Gamedonia session. This means there needs to be a user logged in with Gamedonia. The main exceptions are, for obvious reasons, creating and logging users in. You can also query Master collections without a session (this includes the Get, Search and Count methods).

Working with Entities

The Gamedonia SDK uses native framework types like IDictonary to represent Entities. We think that this solution is the most flexible one because we keep your app data objects agnostic by not forcing you to extend a special Gamedonia data type.

As we mentioned above an Entity is a set of Key-Value pairs, so you can model any kind of data with them. The only requirement is that the _id attribute that represents the unique identifier of the entity will be always present once the entity has been stored onto Gamedonia Data Storage. The _id attribute is managed by Gamedonia so you don't have to do any special task to generate or maintain it.

To understand how to use the Gamedonia Data Storage you have to take into account that you are working with a NoSQL database. That means that you are using a key-value data store that supports nested data structures, and advanced queries. You can find an interesting article on how to model relationships in a NoSQL database here.

Create

When using Gamedonia SDKs, you will use the type Dictonary or Object to populate your collections. In the following example where we are creating a movie entity to be stored in the movies:

IMPORTANT: Before creating an entity or calling any of the following GamedoniaData methods, you need to create a collection in which the call will take effect. You can do it in the Dashboard in the Collections section.

For instance, if you want to call the method GamedoniaData.Create on the collection called "movies", this collection has to exist and have the exact same name.

// Store all the information you want inside a dictionary
Dictionary<string,object> movie = new Dictionary<string,object>();
movie["name"] = "The Godfather";
movie["director"] = "Francis Ford Coppola";
movie["duration"] = "178 minutos";
movie["music"] = "Nino Rota";
 
// Make the request to store the entity inside the desired collection
GamedoniaData.Create("movies", movie, delegate (bool success, IDictionary data){
    if (success){
        //TODO Your success processing 
    }
    else{
        //TODO Your fail processing
    }
});
void MyClass::CreateMovieEntity() {
    CCDictionary* movie = CCDictionary::create();
    parameters->setObject(CCString::create("The Godfather"), "name");
    parameters->setObject(CCString::create("Francis Ford Coppola"), "director");
    parameters->setObject(CCString::create("178 minutes"), "duration");
    parameters->setObject(CCString::create("Nino Rota"), "music");

    // Make the request to store the entity inside the desired collection
    GamedoniaSDKData::create ("movies", movie, this, gamedoniaResponseData_selector(MyClass::MovieCreatedCallback));
}

void MyClass::MovieCreatedCallback(bool success, CCDictionary* movie) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
// Store all the information you want inside a dictionary
NSDictionary * movie = [NSDictionary dictionaryWithObjectsAndKeys:
                           @"The Godfather",@"name",
                           @"Francis Ford Coppola",@"director",
                           @"178 minutes",@"duration",
                           @"Nino Rota",@"music",
                        nil];

// Make the request to store the entity inside the desired collection
[[Gamedonia data] create:@"movies" 
                  entity:movie
                  callback:^(BOOL success, NSDictionary *data) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}];
// Store all the information you want inside an object
var movie:Object = new Object();
movie.name = 'The Godfather';
movie.director = 'Francis Ford Coppola"';
movie.duration = '178 minutes';
movie.music = 'Nino Rota';

// Make the request to store the entity inside the desired collection
GamedoniaData.create("movies", movie, function(success:Boolean, data:Object):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
-- Store all the information you want inside a dictionary
local movie = {}
movie.name = "The Godfather"
movie.director = "Francis Ford Coppola"
movie.duration = "178 minutes"
movie.music = "Nino Rota"

local createCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end

-- Make the request to store the entity inside the desired collection
Gamedonia.Data.create ("movies", movie, createCB)
Request
POST http://api.gamedonia.com/v1/data/collection/create

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
X-Gamedonia-Signature: 7345gss4gs4u8je09d3bfb656829e44b
Content-Type: application/json
{
  <any json data>
}
  1. X-Gamedonia-ApiKey: Required. Private Game Key available on the Dashboard.
  2. X-Gamedonia-Signature. Optional. Content signature generated from the shared secret "master" of the game. Available on the dashboard.
  3. Collection. The collection on which to perform the query.
  4. Message body must include the JSON data to store.
Response
HTTP/1.1 200 OK
Content-Type:application/json
{
  <any json data>
}
Other possible responses
  • HTTP/1.1 401 Unauthorized
    • The signature was invalid or unrecognized ApiKey.

Once the create function is executed you'll get back the stored entity with its _id attribute filled.

All Data Storage operations that modify an Entity on the Gamedonia Backend always return the modified entity back to the client.

Get

You can recover an Entity from your game backend easily if you know the _id attribute of the entity.

GamedoniaData.Get("movies", entity_id, delegate (bool success, IDictionary data){
    if (success){
        //TODO Your success processing
    }
    else{
        //TODO Your fail processing
    }
});
void MyClass::GetMovieEntity(const char *entityId) {
    // Make the request to store the entity inside the desired collection
    GamedoniaSDKData::get ("movies", entityId, this, gamedoniaResponseData_selector(MyClass::MovieEntityInfoCallback));
}

void MyClass::MovieEntityInfoCallback(bool success, CCDictionary* movie) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
[[Gamedonia data] get:@"movies" 
                  entityId:@"<the-entity-id>" 
                  callback:^(BOOL success, NSDictionary *data) {

    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }          
}];
GamedoniaData.get ("movies", entityId, function(success:Boolean, data:Object):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
local getCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end

Gamedonia.Data.get ("movies", entity_id, getCB)
Request
GET http://api.gamedonia.com/v1/data/collection/search?query=[filter]&[modifiers]
X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
  1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
  2. Collection. Required. Collection on which to perform the query.
  3. Query. Required. Entity Identifier.
Response
HTTP/1.1 200 OK
Content-Type:application/json
{
    <json entity>
}

The returned entity will be mapped against an IDictionary to let you work easier with it.

Update

When updating an entity at the Gamedonia backend, you have to options at your disposal: override and merge.

Override

Imagine you have an entity already stored in your Gamedonia Backend and you need to modify, remove or add new key-pairs to it. The easiest way to perform this update is by sending the whole entity data to Gamedonia in override mode so your previous entity will be completely overwritten by the new one, keeping the same _id attribute.

//Dictionary movie ...
GamedoniaData.Update("movies", movie, delegate (bool success, IDictionary data){
    if (success){
        //TODO Your success processing
    } 
    else{
        //TODO Your fail processing
    }
}, true);
void MyClass::UpdateMovieEntity(CCDictionary* movie) {
    //CCDictionary movie with all fields fulfilled ...
    GamedoniaSDKData::update ("movies", movie, true, this, gamedoniaResponseData_selector(MyClass::MovieUpdatedCallback));
}

void MyClass::MovieUpdatedCallback(bool success, CCDictionary* movie) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
//NSMutableDictionary movie ...
[movie setObject:@"The Avengers" forKey:@"name"];
[movie removeObjectForKey:@"duration"];
[movie setObject:5 forKey:@"stars"];

[[Gamedonia data] update:@"movies" 
                  entity:movie
                  overwrite:true
                  callback:^(BOOL success, NSDictionary *data) {

    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }           
}];
//Object movie with all fields fulfilled ...
GamedoniaData.update("movies", movie, true, function(success:Boolean, data:Object):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
local updateCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end

Gamedonia.Data.update ("movies", movie, true, updateCB)
Request

It is the normal case of use. A user validation will be made with the session token to see whether the request is being made from the real logged user or not, and to see if he has an active session.

PUT http://api.gamedonia.com/v1/data/collection/update

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
X-Gamedonia-Signature: 7345gss4gs4u8je09d3bfb656829e44b
Content-Type: application/json
{
  <any json data>
}
  1. X-Gamedonia-ApiKey: Required. Private Game Key available on the Dashboard.
  2. X-Gamedonia-Signature. Optional. Content signature generated from the shared secret "master" of the game. Available on the dashboard.
  3. Collection. The collection on which to perform the query.
  4. Message body must include the JSON data to store.
Response
HTTP/1.1 200 Ok

Merge

The other scenario is when you have an entity with lots of data stored inside and you only need to update a single or few values of the entity. Moving the huge entity up and down the servers is a waste of bandwidth. To solve this problem you can use the merge update, which will allow you to only send to the servers the key-value pairs you want to update.

//Dictionary movie ...
GamedoniaData.Update("movies", movie, delegate (bool success, IDictionary data){
    if (success){
        //TODO Your success processing
    } 
    else{
        //TODO Your fail processing
    }
});
void MyClass::UpdateMovieEntity(CCDictionary* movie) {
    //CCDictionary movie with only the modified fields ...
    GamedoniaSDKData::update ("movies", movie, false, this, gamedoniaResponseData_selector(MyClass::MovieUpdatedCallback));
}

void MyClass::MovieUpdatedCallback(bool success, CCDictionary* movie) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
NSDictionary * movie = [NSDictionary dictionaryWithObjectsAndKeys:
                       @"_id",@"<the-entity-id-to-update>",
                       @"The Godfather",@"name",
                       nil];

[[Gamedonia data] update:@"movies" 
                  entity:movie 
                  overwrite:false
                  callback:^(BOOL success, NSDictionary *data) {

    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }           
}];
//Object movie with only the modified fields ...
GamedoniaData.update("movies", movie, false, function(success:Boolean, data:Object):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
local updateCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end
Gamedonia.Data.update ("movies", movie, false, updateCB)
Request

It is the normal case of use. A user validation will be made with the session token to see whether the request is being made from the real logged user or not, and to see if he has an active session.

POST http://api.gamedonia.com/v1/data/collection/update

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
X-Gamedonia-Signature: 7345gss4gs4u8je09d3bfb656829e44b
Content-Type: application/json
{
  <any json data>
}
  1. X-Gamedonia-ApiKey: Required. Private Game Key available on the Dashboard.
  2. X-Gamedonia-Signature. Optional. Content signature generated from the shared secret "master" of the game. Available on the dashboard.
  3. Collection. The collection on which to perform the query.
  4. Message body must include the JSON data to store.
Response
HTTP/1.1 200 Ok

In addition to the key-value pairs you want to update you need to send the _id attribute in the entity you are updating to let Gamedonia know which entity you want to update.

Remove

There are two ways to delete entities: removing a single entity or removing a set of entities at once.

Remove a single entity

Deleting a single Entity is a straightforward process. All you need to know is the Entity _id attribute and the collection where the Entity is stored.

GamedoniaData.Delete("movies", entity_id, delegate (bool success){ 
    if (success){
        //TODO Your success processing
    }
    else{
        //TODO Your fail processing
    }
});
void MyClass::DeleteMovieEntity(const char *entityId) {
    GamedoniaSDKData::remove ("movies", entityId, this, gamedoniaResponse_selector(MyClass::MovieRemovedCallback));
}

void MyClass::MovieRemovedCallback(bool success) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
[[Gamedonia data] remove:@"movies" 
                  entityId:@"<the-entity-id-to-remove>" 
                  callback:^(BOOL success) {

    if (success) {
        //TODO Your success processing
    } else { 
        //TODO Your fail processing 
    } 
}];
GamedoniaData.del("movies", movieId, function(success:Boolean):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
local removeCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end
Gamedonia.Data.remove ("movies", entity_id, removeCB)
Request
Delete Single Entity
DELETE http://api.gamedonia.com/v1/data/delete/id

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
  1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
  2. Id. Required. Entity Identifier.
Delete Multiple Entities
DELETE http://api.gamedonia.com/v1/data/collection/delete?ids=id1,id2

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
  1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
  2. Collection. Required. Collection on which to perform the query.
  3. Ids. Required. Entity Identifiers.
Response
HTTP/1.1 200 OK
Content-Type:application/json

Remove multiple entities

To delete a set of entities you need to pass this method the list of _id's of the entities to be removed. You can also choose to clean the whole collection (delete all its entities) by toggling a boolean, in which case the set of entities passed as a parameter will be ignored.

GamedoniaData.Delete("movies", entity_id_list, false, delegate (bool success, int num){ 
	if (success){
		//TODO Your success processing
	}
	else{
		//TODO Your fail processing
	}
});

Querying

Queries can be peformed against the Gamedonia backend using the standard NoSQL query syntax of our engine database. The Gamedonia Backend data storage is based in a NoSQL MongoDB database, so you will use its query syntax to perform your searches. You can find documentation related to doing queries using MongoDB syntax here.

All data queries are performed against Collections defined in your app. So before you can perform any kind of query over data you need to create a collection and populate it with some entities.

Creating a collection can be accomplished with a few clicks. Log in to the Dashboard with your access credentials, select a game (or create a new one) and click on Collections.

The query syntax is expressed in JSON format, following the same pattern used to define the entities data. For example:

An empty query {} selects all the entities in a collection and can be implemented like this:

GamedoniaData.Search("movies", "{}", delegate (bool success, IList list){
    if (success){
        //TODO Your success processing
    }
    else {
        //TODO Your fail processing
    }
});
void MyClass::SearchMovie() {
    GamedoniaSDKData::search ("movies", "{}", this, gamedoniaResponseData_selector(MyClass::MovieSearchCallback));
}

void MyClass::MovieSearchCallback(bool success, CCArray* movie) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
[[Gamedonia data] search:@"movies" query:@"{}" callback:^(BOOL success, NSArray *data) {
    if (success) {
        //TODO Your success processing
    } else {
       //TODO Your fail processing
    }
}];
GamedoniaData.search("movies", "{}", function(success:Boolean, data:Object):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
local searchCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end

Gamedonia.Data.search ("movies", query "{}", searchCB)
Request
GET https://api.gamedonia.com/v1/data/collection/search?query=

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
  1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
  2. Collection. Required. Collection on which to perform the query.
Response
HTTP/1.1 200 OK
Content-Type:application/json
{
    <json entity>
}

A single-clause query selects all documents in a collection where a field has a certain value. These are simple equality queries. In the following example we query to get movies whose name is The Godfather.

GamedoniaData.Search("movies", "{\"name\":\"The Godfather\"}", delegate (bool success, IList list){
    if (success){
        //TODO Your success processing
	   if (data != null && data.Count == 1) {
		Dictionary<string, object> movie = (Dictionary<string, object>) data[0];
	   }
    }
    else {
        //TODO Your fail processing
    }
});
void MyClass::SearchMovie() {
    GamedoniaSDKData::search ("movies", "{'name':'The Godfather'}", this, gamedoniaResponseData_selector(MyClass::MovieSearchCallback));
}

void MyClass::MovieSearchCallback(bool success, CCArray* movie) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}
[[Gamedonia data] search:@"movies" query:@"{'name':'The Godfather'}" callback:^(BOOL success, NSArray *data) {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
}];
GamedoniaData.search("movies", "{'name':'The Godfather'}", function(success:Boolean, data:Object):void {
    if (success) {
        //TODO Your success processing
    } else {
        //TODO Your fail processing
    }
});
local searchCB = function (succes, data)
    if success then
        -- TODO Your success processing
    else
        -- TODO Your fail processing
    end
end

Gamedonia.Data.search ("movies", query "{'name':'The Godfather'}", searchCB)
Request
GET https://api.gamedonia.com/v1/data/collection/search?query={'name':'The Godfather'}

X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
  1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
  2. Collection. Required. Collection on which to perform the query.
Response
HTTP/1.1 200 OK
Content-Type:application/json
{
    <json entity>
}

To learn more about MongoDB querying you can check their MongoDB Manual page.

Operators

To build more complex queries you will need to use query Operators. Let's review what kind of operators can be used to build queries:

Comparison

$ne. Selects the documents where the value of the field is not equal (i.e. !=) to the specified value. This includes documents that do not contain the field.

Syntax: {field: {$ne: value} }

$lt. Selects the documents where the value of the field is less than (i.e. <) the specified value.

Syntax: {field: {$lt: value} }

$lte. Selects the documents where the value of the field is less than or equal to (i.e. <=) the specified value.

Syntax: {field: {$lte: value} }

$gt. Selects those documents where the value of the field is greater than (i.e. >) the specified value.

Syntax: {field: {$gt: value} }

$gte. Selects the documents where the value of the field is greater than or equal to (i.e. >=) a specified value (e.g. value.)

Syntax: {field: {$gte: value} }

$in. Selects the documents where the field value equals any value in the specified array (e.g. <value1>, <value2>, etc.)

Syntax: {field: { $in: [<value1>, <value2>, ... <valueN> ] } }

$nin. Selects the documents where:

Syntax: {field: { $nin: [ <value1>, <value2> ... <valueN> ]} }

  • the field value is not in the specified array or
  • the field does not exist.

$all. Selects the documents where the field holds an array and contains all elements (e.g. <value>, <value1>, etc.) in the array.

Syntax: {field: { $all: [ <value> , <value1> ... ]} }

Logical

$and. Performs a logical AND operation on an array of two or more expressions (e.g. <expression1>, <expression2>, etc.) and selects the documents that satisfy all the expressions in the array. The $and operator uses short-circuit evaluation. If the first expression (e.g. <expression1>) evaluates to false, MongoDB will not evaluate the remaining expressions.

Syntax: {$and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }

$or. Performs a logical OR operation on an array of two or more <expressions> and selects the documents that satisfy at least one of the <expressions>.

Syntax: {$or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ]}

$nor. Performs a logical NOR operation on an array of two or more <expressions> and selects the documents that fail all the <expressions> in the array.

Syntax: {$nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] }

$not. Performs a logical NOT operation on the specified <operator-expression> and selects the documents that do not match the <operator-expression>. This includes documents that do not contain the field.

Syntax: {field: { $not: { <operator-expression> } } }

Element

$exist. Selects the documents that contain the field if <boolean> is true. If <boolean> is false, the query only returns the documents that do not contain the field. Documents that contain the field but has the value null are not returned.

Syntax: {field: { $exists: <boolean> } }

$type. Selects the documents where the value of the field is the specified BSON type. See supported data types here.

Syntax: {field: { $type: <BSON type> }}

$mod. Selects the documents where the field value divided by the divisor has the specified remainder.

Syntax: {field: { $mod: [ divisor, remainder ]} }

    Identifier

    $oid. Selects the documents that have value as identifier. All objects will have their own unique object identifier at the _id field. Searching for documents using the _id field without the $oid operator will NOT work.

    Syntax:{_id: { $oid: value } }

    Javascript

    $regexp. Provides regular expression capabilities for pattern matching strings in queries. MongoDB uses Perl compatible regular expressions (i.e. “PCRE.”).

    Syntax: {field: { $regex: <regular-expression>, $options: <options> } }.

    • $options. There are four option flags.
      • i toggles case insensitivity, and allows all letters in the pattern to match upper and lower cases.
      • m toggles multiline regular expression. Without this option, all regular expressions match within one line. If there are no newline characters (e.g. \n) or no start/end of line construct, the m option has no effect.
      • x toggles an “extended” capability. When set, $regex ignores all white space characters unless escaped or included in a character class.
        Additionally, it ignores characters between an un-escaped # character and the next new line, so that you may include comments in complicated patterns. This only applies to data characters; white space characters may never appear within special character sequences in a pattern.
      • s allows the dot (e.g. .) character to match all characters including newline characters.

    Modifiers

    Queries can also optionally include modifiers to limit, skip or sort the retrieved results from the Gamedonia Backend.

    Limit and Skip

    The most common use case for these modifiers is query results pagination. Imagine you have a huge collection of movies and you want to show a paginated table of 20 movies per page. You can achieve that by setting the limit=20 (you will get a maximum of 20 elements as a result) and the skip modifier to skip=20 (this would ignore the first 20 elements).

    GamedoniaData.Search("movies", "{}", 20, null, 20, delegate (bool success, IList list){
        if (success){
            //TODO Your success processing
        }
        else {
            //TODO Your fail processing
        }
    });
    void MyClass::SearchMovie() {
        // Search(Collection, query, limit, skip, object, delegate_method)
        GamedoniaSDKData::search ("movies", "{}", 20, "", 20, this, gamedoniaResponseData_selector(MyClass::MovieSearchCallback));
    }
    
    void MyClass::MovieSearchCallback(bool success, CCArray* movie) {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    }
    
    [[Gamedonia data] search:@"movies" query:@"{}" limit:20 skip:20 callback:^(BOOL success, NSArray *data) {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    }];
    GamedoniaData.search("movies", "{}", 20, null, 20, function(success:Boolean, data:Object):void {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    });
    
    local searchCB = function (succes, data)
        if success then
            -- TODO Your success processing
        else
            -- TODO Your fail processing
        end
    end
    
    Gamedonia.Data.search ("movies", query "{}", searchCB, limit:20, nil, skip:20)
    
    Request
    GET https://api.gamedonia.com/v1/data/collection/search?query={}&limit=20&skip=20
    
    X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
    
    1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
    2. Collection. Required. Collection on which to perform the query.
    Response
    HTTP/1.1 200 OK
    Content-Type:application/json
    {
        <json entity>
    }

    Sort

    Query results can also be sorted Ascending or Descending, you only need to specify the field you want to sort with and choose the sorting direction.

    For example let's sort our movies by name in ascending order.

    GamedoniaData.Search("movies", "{}", 20, "{name:1}", delegate (bool success, IList list){
        if (success){
            //TODO Your success processing
        }
        else {
            //TODO Your fail processing
        }
    });
    
    void MyClass::SearchMovie() {
        // Search(Collection, query, limit, sort, skip, object, delegate_method)
        GamedoniaSDKData::search ("movies", "{}", 20, "{'name':1}", 20, this, gamedoniaResponseData_selector(MyClass::MovieSearchCallback));
    }
    
    void MyClass::MovieSearchCallback(bool success, CCArray* movie) {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    }
    
    [[Gamedonia data] search:@"movies" query:@"{}" limit:20 sort:@"{'name':1}" skip:20*pageIndex callback:^(BOOL success, NSArray *data) {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    }];
    
    GamedoniaData.search("movies", "{}", 20, "{'name:1}", 20, function(success:Boolean, data:Object):void {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    });
    
    local searchCB = function (succes, data)
        if success then
            -- TODO Your success processing
        else
            -- TODO Your fail processing
        end
    end
    
    Gamedonia.Data.search ("movies", query "{}", searchCB, limit:20, sort "{'name:1}", skip:20)
    
    Request
    GET https://api.gamedonia.com/v1/data/collection/search?query={}&limit=20&skip=20&sort={'name:1'}
    
    X-Gamedonia-ApiKey: 4cb5c78cdf4c11e09d3bfb656829e44b
    
    1. X-Gamedonia-ApiKey: Required. Private Game master key available on the Dashboard.
    2. Collection. Required. Collection on which to perform the query.
    Response
    HTTP/1.1 200 OK
    Content-Type:application/json
    {
        <json entity>
    }

    Count

    Another type of query we can use is the count function. This will return the number of items found with a given query. We can specify any query used for searching data on a collection, but instead of returning the matching objects, this will give us the number of objects found.

    For example we can count the number of movies rated over 4 points as in this code:

    GamedoniaData.Count("movies", "{\"rating\":{$gt:4}}", delegate (bool success, int count) { 
    	if (success) { 
    		//TODO Your success processing 
    	} else {
    		//TODO Your fail processing 
    	}
    });
    
    void MyClass::CountMovies() {
        GamedoniaSDKData::count ("movies", "{\"rating\":{$gt:4}}", this, gamedoniaResponseLong_selector(MyClass::MoviesCountCallback));
    }
    
    void MyClass::MoviesCountCallback(bool success, long count) {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    }
    
    GamedoniaData.count("movies", "{\"rating\":{$gt:4}}", function(success:Boolean, count:Number):void {
        if (success) {
            //TODO Your success processing
        } else {
            //TODO Your fail processing
        }
    });
    
    local searchCB = function (succes, count)
        if success then
            -- TODO Your success processing
        else
            -- TODO Your fail processing
        end
    end
    
    Gamedonia.Data.count ("movies", "{\"rating\":{$gt:4}}", searchCB)
    
    class MyCbresponse : public GamedoniaCallbackHandler
    {
    public:
        void onCountMoviesResponse(bool success, unsigned long count)
        {
            if (success) {
                //TODO Your success processing
            } else {
                //TODO Your fail processing
            }
        }
    };
    
    //profile only contains few of the fields of the full profile to modify
    void MyClass::countMovies()
    {
        MyCbresponse* response = new MyCbresponse();
        GamedoniaData::count("movies", "{\"rating\":{$gt:4}}", response, gamedoniaResponseDataCount_selector(MyCbresponse::onCountMoviesResponse));
        response->release();
    }
    

    Special types

    Here we will show you a coupple of examples on how to query using advanced types.

    Querying the _id field

    Every entity in a collection has a unique _id field that identifies it uniquely. When querying for a specific _id, you can't just try to match the string to that field. You need to use the MongoDB $oid operator, here's an example on how to do that:

    			string idMovie = "55eda670e4b02c641399a60e";
    			
    			GamedoniaData.Search("movies", "{_id:{$oid:'"+idMovie+"'}}", delegate (bool success, IList list){
    				
    				if (success) {
    					//TODO Your success processing 
    					
    				} else {
    					//TODO Your fail processing 
    				}
    			});
    		

    Querying dates

    Gamedonia gives support to the Date type on the whole platform. When querying a collection using a date field, you will need to pass the value with a special format. Here's an example how. We search all entities with a field of type Date called the_date with a date later than 2009. As you can see, you need to introduce the date inside an ISODate structure.

    			GamedoniaData.Search("movies", "{the_date:{$gte:ISODate(\"2010-01-01T00:00:00.000Z\")}}", delegate (bool success, IList list){
    
    				if (success) {
    					//TODO Your success processing 
    					
    				} else {
    					//TODO Your fail processing 
    				}
    			});
    		

    Access without session

    The basic rule in Gamedonia is that every transaction should occur under a valid user session. There is a useful exception to this, which lets you obtain objects from a Master collection before logging a user in. This may be used to show static parameters (configurations, cards, etc) before a user actually logs in even for the first time.

    These are the methods you can use without an existing Gamedonia session when querying on Master collections (to query a normal collection, you will need to log a user in first).

    • Get

    • Count

    • Search

    You may find it useful to be able to check if there is an active Internet connection and connectivity to the Gamedonia servers. See how to do that here.

    BSON Data types

    BSON is a binary serialization format used to store documents and make remote procedure calls in MongoDB. This is a list of BSON types and their coreesponding number, which can be used to query docuemnts using the $type operator.

    • Double: 1
    • String: 2
    • Object: 3
    • Array: 4
    • Binary data: 5
    • Object id: 7
    • Boolean: 8
    • Date: 9
    • Null: 10
    • Regular Expression : 11
    • JavaScript: 13
    • Symbol: 14
    • JavaScript (with scope): 15
    • 32-bit integer: 16
    • Timestamp: 17
    • 64-bit integer: 18
    • Min key: 255
    • Max key: 127

    Now you’ve learned how you can manage your data in Gamedonia, follow up with our Data storage tutorial. Learn how to add and retrieve data from Gamedonia and create your own data structures.