-
Notifications
You must be signed in to change notification settings - Fork 1
3. Data fetching (GET requests)
To fetch data, such as created Clans or registered Profiles, a GET request can be executed. This API supports two types of GET requests:
- Getting list of existing objects (Clans, Profiles)
- Getting detailed information about one particular object
Depending on the requirements, one of the two types can be used. For example, if there is a need to display a list with information about existing Clans, the first type should be chosen. If only one Clan's data should be shown, such as on a Clan page, the second type should be chosen. Usually, it is obvious which type is more suitable, but it is important to remember that no unnecessary data should be fetched. This can be managed by using pagination.
The standard forms of the GET endpoint:
- /collection_name list of objects ( /clan )
- /collection_name/object_id one object ( /clan/651d5a500d067b29208403f7 )
Notice that no body is required for GET requests, but for some of them, the Authorization header is needed. All responses are in JSON format.
When a list of objects needs to be displayed, it is good to evaluate how many of these objects are actually required for the page. For example, if the expected display is on a mobile phone and there is room for only 5 Clans' data on one screen, and there is a requirement for not making long-scrolling lists, requesting 50 Clans is unnecessary. Such a problem can be solved in two ways: on the game and web pages side or on the API side.
The first approach is to request 50 Clans' data, save it to an array, and retrieve 5 at a time from this array. This approach alone may work only if there are no more than 50 Clans in existence. After retrieving the first 50 Clans, the next 50 should be retrieved from the API. However, this is not the best approach because requesting large amounts of data uses additional device RAM and adds extra load on the API. Notice that if only one device is requesting the data at a time, it is fine, but usually, there are many devices, and the API response speed can slow down. This is why the second approach is better.
The second approach is handling everything on the API side, called pagination. The idea is similar to the first approach, where an array is used and, on each step, the next 5 Clans are retrieved. In pagination, instead of an array, the whole database is used, and these steps are called pages. The page has two parameters: order number and size. The size determines how many objects are retrieved at once (in the previous example, it is 5 Clans). The order number of the page determines which part of the "array" is retrieved. This approach is simpler to use in game and web page and is also more optimized.
In this API, pagination can be used with limit and page query pairs. The limit is the page size, and the page is the page order number. For example:
- /clan?limit=5&page=1 get first 5 Clans
- /clan?limit=5&page=2 get second 5 Clans
By default, the limit equals 20, which is the maximum amount that can be requested at one time. If there is a need to increase it, make a new issue in the Issues tab. By default, the page equals 1. If no pagination query parameters are specified, the first 20 objects are returned.
Notice that on different pages, different pagination settings can be used. As mentioned previously, the amount of data retrieved should be optimized.
The response also contains a paginationData field, which is an object containing helpful data that can be used in the UI:
"paginationData": {
"currentPage": 1, // Requested page number
"limit": 5, // Specified limit
"offset": 0, // How much objects are behind = (currentPage-1)*limit
"itemCount": 40, // How much objects found, only for the first page
"pageCount": 8 // How much pages where are, only for the first page
}
For requests made for particular objects, such as /clan/clan_id or /player/player_id, it is possible to request additional data using the queries "with" and "all". These queries allow the API to return related objects from neighboring collections. For example, if you request a Clan with a particular _id and include the with=Player query, both the Clan data and an array of Players in that Clan will be returned:
// Collections names are separated by underscore (if there is only one collection required no underscore needed)
// GET /clan/686b461abdf0400db327ffad?with=Player_Stock
{
"data": {
"Clan": {
"_id": "686b461abdf0400db327ffad",
"name": "my clan",
//...
"Player": [
// Players...
],
"Stock": [
// Stocks...
],
}
}
}
Using the "all" query results in all neighboring collections being returned. In the case of a Clan, this would include Player, Stock, and SoulHome. However, it is recommended not to use the all query if only some of the neighboring collections are required.
Neighboring collections can be seen from the ER diagram. Another approach is to make a GET request with the "all" query to see all neighboring collections. However, if no neighboring objects are found, nothing will be returned. Therefore, using the ER diagram is the best approach.
The API offers ways to search for specific objects and sort results using the queries: "search", "sort", and "desc".
The search query can contain multiple settings, with syntax similar to programming languages. If multiple search expressions are needed, each expression in the query must be separated by a semicolon.
An expression consists of a field name, an operator, and a value. For example, to find all Clans with gameCoins equal to 5, the query would look like this:
/clan?search=gameCoins=5
For multiple expressions, such as finding gameCoins in the range from 2 to 5 (2 included, 5 not included):
/clan?search=gameCoins>=2;AND;gameCoins<5
For string type values, use double quotes. It is also possible to use a dot as a wildcard character, which represents one or more characters:
/clan=search=name="my clan" //name equals exactly to "my clan"
/clan=search=name="clan." //name starts with "clan"
/clan=search=name=".clan" //name ends with "clan"
/clan=search=name=".clan." //name contains "clan" in the middle
Searching by multiple fields at once is also possible:
/clan?search=gameCoins>=1;AND;gameCoins<=3;AND;name="kl."
The OR operator can be used instead of AND:
/clan?search=gameCoins>=1;AND;gameCoins<=3;OR;name="cl." //gameCoins from 1 to 3 or name starts with "cl"
The OR operator works like in if-statements and splits the query part into separate ones:
// Equivalent of if( (gameCoins>=1 && gameCoins<=3) || (name="clan" && tag="my tag") )
/clan?search=gameCoins>=1;AND;gameCoins<=3;OR;name="clan";AND;tag="my tag" /
The search query for an input box could look as follows:
/clan?name=user_inputted_text
It is good to optimize such queries. For example, if a user is inputting a Clan name at a rate of 1 character per second, and the response to such a search query can be returned only after 2 seconds, it makes sense to add some delay before making a search query. After each inputted character, a timer for 1-2 seconds can be set so that only when the user stops inputting text is the query sent. This can help avoid unnecessary requests to the API and reduce server load.
Sorting objects can be achieved using the "sort" and "desc" queries. The "sort" query specifies the field by which the objects will be sorted, while the "desc" query changes the sorting order to opposite:
/clan?sort=gameCoins //Sort Clans by gameCoins from smaller to larger
/clan?sort=gameCoins&desc //Sort Clans by gameCoins from larger to smaller
It is also possible to sort the results by multiple fields by specifying field names separated by a comma. However, this is not recommended as the results might be hard to predict:
/clan?sort=gameCoins,playerCount //Sort Clans by gameCoins and playerCount
By default, the sorting order is ascending for numbers (from smaller to larger) and alphabetical for strings (from a to z).
Sorting can be applied alone or in combination with the search query. For example:
/clan?sort=gameCoins //Sort all Clans by gameCoins
/clan?search=name="clan."&sort=gameCoins //Sort Clans by gameCoins, which name starts with "clan"