Querying KiiObjects

You can run a conditional query for KiiObjects in a bucket. For example: a query that gets up to 10 KiiObjects that have a value of more than 10 for a key named "count" in descending order.

See Query Examples for various query examples.

Executing a KiiObject query

Defining a query condition

You can define a query condition using the following methods of the KiiClause class:

Method Query condition
equals(_:value:) Match when the field value is equal to the specified value.
notEquals(_:value:) Match when the field value is not equal to the specified value. The condition does not match if the specified field does not exist.
greaterThan(_:value:) Match when the field value is greater than the specified value.
greaterThanOrEqual(_:value:) Match when the field value is greater than or equal to the specified value.
lessThan(_:value:) Match when the field value is less than the specified value.
lessThanOrEqual(_:value:) Match when the field value is less than or equal to the specified value.
in(_:value:) Match when the field value is equal to one of the specified values. Up to 200 values can be specified. The method needs to match with the type of the JSON field.
startsWith(_:value:) Match when the field value (String) starts with the specified string.
geoBox(_:northEast:southWest:) Match when the field value (GeoPoint) is inside the specified GeoBox (rectangular area).
geoDistance(_:center:radius:putDistanceInto:) Match when the field value (GeoPoint) is inside the specified GeoDistance (circular area).
hasField(_:andType:) Match when the field has the specified field type (currently supported types are KiiFieldTypeString, KiiFieldTypeInteger, KiiFieldTypeDecimal, and KiiFieldTypeBoolean).

You can concatenate multiple query conditions using the following methods of the KiiClause class:

Method --- How to concatenate
andClauses(_:) Concatenate query conditions with an "AND" operator.
orClauses(_:) Concatenate query conditions with an "OR" operator.
notClause(_:) Concatenate query conditions with a "NOT" operator. The argument is a KiiClause instance. It can be a single-condition clause or a multiple-condition clause concatenated by the andClauses(_:) or orClauses(_:) method.

See the appledoc to learn more about KiiClause.

Querying with the notClause(_:) method can decrease performance but you might be able to transform the clause to avoid a not operator. See Transforming a not clause for more information.

Creating a query instance and executing a query

To execute a query, you first need to create a query instance. This is done by creating a KiiQuery instance with a KiiClause instance that contains a query condition. If you create a KiiQuery instance without a KiiClause instance, the query will return all KiiObjects in the target bucket (this is equivalent to an "all" query).

You can fine-tune a query instance by using the following methods and property.

  • sortByAsc(_:) sorts query results in ascending order by the specified field.
  • sortByDesc(_:) sorts query results in descending order by the specified field.
  • limit is the maximum number of KiiObjects returned as query results on the best-effort basis. The maximum value is 200.

The detailed specification of the query feature is as below:

  • The sortByAsc(_:) and sortByDesc(_:) methods can be applied to only one field.

  • If neither sortByAsc(_:) nor sortByDesc(_:) methods is specified, the query results will be in arbitrary order. If the limit property is not set, the maximum number of KiiObjects returned by a query may be up to 200 by default.

  • The limit property is on a best-effort basis. For example, Kii Cloud does not guarantee to return all 40 KiiObjects if the limit property is set to 40 and there are more than 40 KiiObjects that satisfy the query condition (this could happen for performance optimization purposes).

  • If you are going to have more than 200 query results, you will need to use the pagination to divide them into several pages.

  • The sortByAsc(_:) and sortByDesc(_:) methods sort query results by an integer field in numerical order and by a string field in dictionary order.

  • Query and sort do not work properly if the type of the field values is not consistent among KiiObjects.

  • Strings are queried in a case-sensitive manner. For example, if you query with a string of "alice", "Alice" stored in a KiiObject will not be returned.

  • Query and sort might not work as expected for real number fields. Real numbers whose fractional part is zero are treated as integers. Therefore, for example, 1.0 will be indexed as an integer 1 while 1.1 will be indexed as a real number 1.1. You cannot get the expected result because the difference between the different types of values will not be correctly evaluated. If you need to query or sort KiiObjects with a real number field, convert real numbers to integers by multiplying them with 10, 100, and so forth. Then save the converted integers in an integer field to use when you run a query.

  • Only the first-level fields within the JSON expression can be queried. You cannot get fields at the subsequent levels because fields at those levels are not indexed.

  • When you are using the in(_:value:) method, make sure that the type of each element in the NSArray matches with the type of the JSON field to be queried. For example, a JSON string {"id" : 123} does not match with an NSArray that contains strings but an NSArray that contains numeric values. When you use an NSArray that contains any float or double values, do not mix decimals and integers in the array elements.

  • Queryable fields must have the field name up to 250 characters and a value (String) up to 190 characters. Key-value pairs that exceed these limits will not be returned by any query using the field.

To execute a query for KiiObjects, use the execute(_:_:) method of the target bucket with a query instance.

See the appledoc to learn more about the KiiQuery class.

The performance of query and sort operations can deteriorate if there are numerous KiiObjects. See Performance for more information.

Using predefined keys for query

In addition to key-value pairs created by your mobile app, you can use predefined keys for query.

Predefined keys include various fields such as the KiiObject ID and created time. For the list of predefined keys, see Predefined keys.

Getting query results

Query results will be returned as an NSArray with KiiObject objects as elements. If the results are split across multiple pages (e.g. the limit property is set to 10 and the query returned 30 KiiObjects), Kii Cloud will return a KiiQuery instance along with the NSArray. You can get the remaining query results by executing the query with this KiiQuery instance.

The SDK might indicate that there are more KiiObjects when actually there are not any, that is to say, the SDK might return a non-nil value in nextQuery. It might happen when the number of KiiObjects returned from the server at a time and the number of KiiObjects that meet the query condition are the same. You should be aware that an empty result might be returned when an attempt is made to get a next page.

You need to handle the paging by yourself if you want to show a fixed amount of query results at a time, for example on the Web. The query results can be obtained only in the forward direction, and the number of results may not be constant because the query mechanism works on the best-effort basis. You might want to get the number of KiiObjects first and uses this number to control the paging.