Query Examples

See the following examples of various queries:

Querying all KiiObjects in a bucket

Let us start with the simplest example: querying all KiiObjects in a bucket. This example assumes that all the query results are returned at once without the pagination.

Swift 3:

  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Create a query that returns all KiiObjects.
    let allQuery = KiiQuery(clause: nil)
    
    // Create a placeholder for any paginated queries.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      let results = try bucket.executeQuerySynchronous(allQuery, nextQuery: &nextQuery)
      // Do something with the result.
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Create a query that returns all KiiObjects.
    let allQuery = KiiQuery(clause: nil)
    
    // Create an array for storing all returned KiiObjects.
    var allResults = [Any]()
    
    // Query KiiObjects.
    bucket.execute(allQuery) { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Do something with the result.
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Create a query that returns all KiiObjects.
    KiiQuery *allQuery = [KiiQuery queryWithClause:nil];
    
    // Create a placeholder for any paginated queries.
    KiiQuery *nextQuery;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:allQuery
                                             withError:&error
                                               andNext:&nextQuery];
    if (error != nil) {
      // Handle the error.
      return;
    }
    // Do something with the result.
     
  • // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Create a query that returns all KiiObjects.
    KiiQuery *allQuery = [KiiQuery queryWithClause:nil];
    
    // Query KiiObjects.
    [bucket executeQuery:allQuery
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      // Do something with the result.
    }];

Here is what is happening in the sample code:

  • Creates a KiiQuery instance without a KiiClause instance (i.e. specifying nil). This query will get all KiiObjects.
  • Queries KiiObjects by calling the executeQuery(_:_:) method in the target bucket by passing the query instance.

Executing an "all" query in a bucket will return all KiiObjects in it.

If you cannot get the expected result, check if you are querying the bucket in the correct scope (See here for more discussion).

Querying with multiple conditions

Next, let's query KiiObjects with the following conditions:

  • The field "gender" has a value of "Female".
  • The field "age" has a value greater than 18.
  • Sort the query results in ascending order by the field "age".
  • Limit the number of query results returned per call to 10.

Swift 3:

  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Define clauses.
    let clause1 = KiiClause.equals("gender", value: "Female")
    let clause2 = KiiClause.equals("age", value: NSNumber(value: 18 as Int))
    
    // Define an And clause with the above clauses.
    let totalClause = KiiClause.andClauses([clause1, clause2])
    
    // Create a query with the And clause.
    let query = KiiQuery(clause: totalClause)
    
    // Define how to output the query result.
    query.sort(byAsc: "age")
    query.limit = 10
    
    // Create an array for storing all returned KiiObjects.
    var allResults = [Any]()
    
    // Create a placeholder for any paginated queries.
    // If all the queried KiiObjects cannot be returned at once,
    // the placeholder will have a non-nil value that means
    // there is more data to retrieve.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      var results = try bucket.executeQuerySynchronous(query, nextQuery: &nextQuery)
    
      // Add the KiiObjects returned by this query to the "allResults" array.
      allResults.append(results as AnyObject)
    
      var nextQuery2 : KiiQuery?
    
      // If there is more data to retreive
      if nextQuery != nil {
        // Query the next 10 KiiObjects with pagination.
        results = try bucket.executeQuerySynchronous(nextQuery!, nextQuery: &nextQuery2)
    
        // Add the KiiObjects returned by this query to the "allResults" array.
        allResults.append(results as AnyObject)
      }
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Define clauses.
    let clause1 = KiiClause.equals("gender", value: "Female")
    let clause2 = KiiClause.equals("age", value: NSNumber(value: 18 as Int))
    
    // Define an And clause with the above clauses.
    let totalClause = KiiClause.andClauses([clause1, clause2])
    
    // Create a query with the And clause.
    let query = KiiQuery(clause: totalClause)
    
    // Define how to output the query result.
    query.sort(byAsc: "age")
    query.limit = 10
    
    // Create an array for storing all returned KiiObjects.
    var allResults = [Any]()
    
    // Query KiiObjects.
    bucket.execute(query) { (firstQuery : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Add the KiiObjects returned by this query to the "allResults" array.
      allResults.append(contentsOf: results!)
    
      // If there is more data to retreive
      if nextQuery != nil {
        // Query the next 10 KiiObjects with pagination.
        bucket.execute(nextQuery! , with: { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery2 , error : Error?) -> Void in
          if error != nil {
            // Handle the error.
            return
          }
    
          // Add the KiiObjects returned by this query to the "allResults" array.
          allResults.append(contentsOf: results!)
        })
      }
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Define clauses.
    KiiClause *clause1 = [KiiClause equals:@"gender"
                                     value:@"Female"];
    KiiClause *clause2 = [KiiClause greaterThan:@"age"
                                          value:[NSNumber numberWithInt:18]];
    
    // Define an And clause with the above clauses.
    KiiClause *totalClause = [KiiClause andClauses:@[clause1, clause2]];
    
    // Create a query with the And clause.
    KiiQuery *query = [KiiQuery queryWithClause:totalClause];
    
    // Define how to output the query result.
    [query sortByAsc:@"age"];
    [query setLimit:10];
    
    // Create an array for storing all returned KiiObjects.
    NSMutableArray *allResults = [NSMutableArray array];
    
    // Create a placeholder for any paginated queries.
    // If all the queried KiiObjects cannot be returned at once,
    // the placeholder will have a non-nil value that means
    // there is more data to retrieve.
    KiiQuery *nextQuery = nil;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:query
                                             withError:&error
                                               andNext:&nextQuery];
    if (error != nil) {
      // Handle the error.
      return;
    }
    
    // Add the KiiObjects returned by this query to the "allResults" array.
    [allResults addObjectsFromArray:results];
    
    // If there is more data to retrieve
    if (nextQuery != nil) {
      KiiQuery *nextQuery2 = nil;
    
      // Query the next 10 KiiObjects with pagination.
      results = [bucket executeQuerySynchronous:nextQuery
                                      withError:&error
                                        andNext:&nextQuery2];
      if (error != nil) {
        // Handle the error.
        return;
      }
    
      // Add the KiiObjects returned by this query to the "allResults" array.
      [allResults addObjectsFromArray:results];
    }
  • // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Define clauses.
    KiiClause *clause1 = [KiiClause equals:@"gender"
                                     value:@"Female"];
    KiiClause *clause2 = [KiiClause greaterThan:@"age"
                                          value:[NSNumber numberWithInt:18]];
    
    // Define an And clause with the above clauses.
    KiiClause *totalClause = [KiiClause andClauses:@[clause1, clause2]];
    
    // Create a query with the And clause.
    KiiQuery *query = [KiiQuery queryWithClause:totalClause];
    
    // Define how to output the query result.
    [query sortByAsc:@"age"];
    [query setLimit:10];
    
    // Create an array for storing all returned KiiObjects.
    NSMutableArray *allResults = [NSMutableArray array];
    
    // Query KiiObjects.
    [bucket executeQuery:query
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    
      // Add the KiiObjects returned by this query to the "allResults" array.
      [allResults addObjectsFromArray:results];
    
      // If there is more data to retrieve
      if (nextQuery != nil) {
        // Query the next 10 KiiObjects with pagination.
        [bucket executeQuery:nextQuery
                   withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
          if (error != nil) {
            // Handle the error.
            return;
          }
    
          // Add the KiiObjects returned by this query to the "allResults" array.
          [allResults addObjectsFromArray:results];
        }];
      }
    }];

Here is what is happening in the sample code:

  • Creates query conditions by calling the equals() and greaterThan() methods. Then creates a KiiClause instance by concatenating these two conditions with the andClauses(_:) method. Finally, the code creates a KiiQuery instance with this KiiClause instance.
  • Calls the sort(byAsc:) method of the KiiQuery instance to define the sort order.
  • Sets the limit property of the KiiQuery instance to the maximum number of KiiObjects returned in each query result set.
  • Queries KiiObjects by calling the execute(_:_:) method in the target bucket by passing the query instance.
  • Parses the query results (In this sample, we are appending all returned KiiObjects onto allResults).

In this example, query results are parsed in consideration of pagination:

  • After parsing through the query results, check the KiiQuery instance (nextQuery) that is returned with the query results.
  • If the KiiQuery instance is not empty, execute the execute(_:_:) method again with this instance to get the next 10 KiiObject results.

Querying with geolocation data

Let us now see how to query using geolocation data as a query condition.

Suppose that a KiiObject has a field named "location" whose value is a GeoPoint object as shown in the following sample code:

Swift 3:

  • let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Create a KiiObject.
    let object = bucket.createObject()
    let point = KiiGeoPoint(latitude: 35.661561, andLongitude: 139.769595)
    object.setGeoPoint(point, forKey: "location")
    do{
      // Save the KiiObject.
      try object.saveSynchronous()
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Create a KiiObject.
    let object = bucket.createObject()
    let point = KiiGeoPoint(latitude: 35.661561, andLongitude: 139.769595)
    object.setGeoPoint(point, forKey: "location")
    
    // Save the KiiObject.
    object.save { (object : KiiObject?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    }

Objective-C:

  • NSError *error = nil;
    
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Create a KiiObject.
    KiiObject *object = [bucket createObject];
    KiiGeoPoint *point = [[KiiGeoPoint alloc] initWithLatitude:35.661561
                                                  andLongitude:139.769595];
    [object setGeoPoint:point
                 forKey:@"location"];
    
    // Save the KiiObject.
    [object saveSynchronous:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
  • KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Create a KiiObject.
    KiiObject *object = [bucket createObject];
    KiiGeoPoint *point = [[KiiGeoPoint alloc] initWithLatitude:35.661561
                                                  andLongitude:139.769595];
    [object setGeoPoint:point
                 forKey:@"location"];
    
    // Save the KiiObject.
    [object saveWithBlock:^(KiiObject *object, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    }];

Here is an example that queries KiiObjects within a rectangle area using a GeoBox() clause.

Swift 3:

  • // Prepare the target bucket to be queried.
    let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Define a GeoBox clause with northeast and southwest points.
    let sw = KiiGeoPoint(latitude: 35.658603, andLongitude: 139.745433)
    let ne = KiiGeoPoint(latitude: 36.069082, andLongitude: 140.07843)
    let clause = KiiClause.geoBox("location", northEast: sw, southWest: ne)
    
    // Create a query with the GeoBox clause.
    let query = KiiQuery(clause: clause)
    
    // Create a placeholder for any paginated queries.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      let results = try bucket.executeQuerySynchronous(query, nextQuery: &nextQuery)
      // Do something with the result.
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Prepare the target bucket to be queried.
    let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Define a GeoBox clause with northeast and southwest points.
    let sw = KiiGeoPoint(latitude: 35.658603, andLongitude: 139.745433)
    let ne = KiiGeoPoint(latitude: 36.069082, andLongitude: 140.07843)
    let clause = KiiClause.geoBox("location", northEast: sw, southWest: ne)
    
    // Create a query with the GeoBox clause.
    let query = KiiQuery(clause: clause)
    
    // Query KiiObjects.
    bucket.execute(query) { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Do something with the result.
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Define a GeoBox clause with northeast and southwest points.
    KiiGeoPoint *sw = [[KiiGeoPoint alloc] initWithLatitude:35.52105
                                               andLongitude:139.699402];
    KiiGeoPoint *ne = [[KiiGeoPoint alloc] initWithLatitude:36.069082
                                               andLongitude:140.07843];
    KiiClause *clause = [KiiClause geoBox:@"location"
                                northEast:ne
                                southWest:sw];
    
    // Create a query with the GeoBox clause.
    KiiQuery *query = [KiiQuery queryWithClause:clause];
    
    // Create a placeholder for any paginated queries.
    KiiQuery *next = nil;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:query
                                             withError:&error
                                               andNext:&next];
    if (error != nil) {
      // Handle the error.
      return;
    }
    // Do something with the result.
     
  • // Prepare the target bucket to be queried.
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Define a GeoBox clause with northeast and southwest points.
    KiiGeoPoint *sw = [[KiiGeoPoint alloc] initWithLatitude:35.52105
                                               andLongitude:139.699402];
    KiiGeoPoint *ne = [[KiiGeoPoint alloc] initWithLatitude:36.069082
                                               andLongitude:140.07843];
    KiiClause *clause = [KiiClause geoBox:@"location"
                                northEast:ne
                                southWest:sw];
    
    // Create a query with the GeoBox clause.
    KiiQuery *query = [KiiQuery queryWithClause:clause];
    
    // Query KiiObjects.
    [bucket executeQuery:query
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      // Do something with the result.
    }];

As shown in the sample code, you define a GeoBox() clause by calling the geoBox(_:northEast:southWest:) method with two GeoPoints, one representing the northeast point, and another one representing the southwest point.

Here is an example of querying KiiObjects within a circular area using a GeoDistance() clause. In this example, we will query KiiObjects that are in the area overlapped by two GeoDistances (GeoDistance1 and GeoDistance2). We will also sort query results in ascending order by the distance from GeoDistance1's center point.

Swift 3:

  • // Prepare the target bucket to be queried.
    let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Define the first GeoDistance clause.
    let center1 = KiiGeoPoint(latitude: 35.658603, andLongitude: 139.745433)
    let clause1 = KiiClause.geoDistance("location", center: center1, radius: 3000, putDistanceInto: "distance_from_center1")
    
    // Define the second GeoDistance clause.
    let center2 = KiiGeoPoint(latitude: 35.681382, andLongitude: 139.766084)
    let clause2 = KiiClause.geoDistance("location", center: center2, radius: 3000, putDistanceInto: nil)
    
    // Create a query with the GeoDistance clauses and set the sort order.
    let totalClause = KiiClause.andClauses([clause1, clause2])
    let query = KiiQuery(clause: totalClause)
    query.sort(byAsc: "_calculated.distance_from_center1")
    
    // Create an array for storing all returned KiiObjects.
    var allResults = [Any]()
    
    // Create a placeholder for any paginated queries.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      let results = try bucket.executeQuerySynchronous(query, nextQuery: &nextQuery)
    
      // Add the KiiObjects returned by this query to the "allResults" array.
      allResults.append(results as AnyObject)
    } catch let error as NSError {
      // Handle the error.
      return
    }
    
    // Get the distance from the center to the location.
    let retObject = allResults[0] as! KiiObject
    let retPoint = retObject.getForKey("location")
    let calc = retObject.getForKey("_calculated") as! NSDictionary
    let distance = calc.object(forKey: "distance_from_center1") as! NSDecimalNumber
  • // Prepare the target bucket to be queried.
    let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Define the first GeoDistance clause.
    let center1 = KiiGeoPoint(latitude: 35.658603, andLongitude: 139.745433)
    let clause1 = KiiClause.geoDistance("location", center: center1, radius: 3000, putDistanceInto: "distance_from_center1")
    
    // Define the second GeoDistance clause.
    let center2 = KiiGeoPoint(latitude: 35.681382, andLongitude: 139.766084)
    let clause2 = KiiClause.geoDistance("location", center: center2, radius: 3000, putDistanceInto: nil)
    
    // Create a query with the GeoDistance clauses and set the sort order.
    let totalClause = KiiClause.andClauses([clause1,clause2])
    let query = KiiQuery(clause: totalClause)
    query.sort(byAsc: "_calculated.distance_from_center1")
    
    // Create an array for storing all returned KiiObjects.
    var allResults = [Any]()
    
    // Query KiiObjects.
    bucket.execute(query) { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Add the KiiObjects returned by this query to the "allResults" array.
      allResults.append(contentsOf: results!)
    
      // Get the distance from the center to the location.
      let retObject = allResults[0] as! KiiObject
      let retPoint = retObject.getForKey("location")
      let calc = retObject.getForKey("_calculated") as! NSDictionary
      let distance = calc.object(forKey: "distance_from_center1") as! NSDecimalNumber
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Define the first GeoDistance clause.
    KiiGeoPoint *center1 = [[KiiGeoPoint alloc] initWithLatitude:35.658603
                                                    andLongitude:139.745433];
    KiiClause *clause1 = [KiiClause geoDistance:@"location"
                                         center:center1
                                         radius:3000
                                putDistanceInto:@"distance_from_center1"];
    
    // Define the second GeoDistance clause.
    KiiGeoPoint *center2 = [[KiiGeoPoint alloc] initWithLatitude:35.681382
                                                    andLongitude:139.766084];
    KiiClause *clause2 = [KiiClause geoDistance:@"location"
                                         center:center2
                                         radius:3000
                                putDistanceInto:nil];
    
    // Create a query with the GeoDistance clauses and set the sort order.
    KiiClause *totalClause = [KiiClause andClauses:@[clause1, clause2]];
    KiiQuery *query = [KiiQuery queryWithClause:totalClause];
    [query sortByAsc:@"_calculated.distance_from_center1"];
    
    // Create an array for storing all returned KiiObjects.
    NSMutableArray *allResults = [NSMutableArray array];
    
    // Create a placeholder for any paginated queries.
    KiiQuery *next = nil;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:query
                                             withError:&error
                                               andNext:&next];
    if (error != nil) {
      // Handle the error.
      return;
    }
    // Add the KiiObjects returned by this query to the "allResults" array.
    [allResults addObjectsFromArray:results];
    
    // Get the distance from the center to the location.
    KiiObject *retObj = [allResults objectAtIndex:0];
    KiiGeoPoint *retPoint = [retObj getGeoPointForKey:@"location"];
    NSDictionary* calc = [retObj getObjectForKey:@"_calculated"];
    NSDecimalNumber *distance = [calc objectForKey:@"distance_from_center1"];
  • // Prepare the target bucket to be queried.
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Define the first GeoDistance clause.
    KiiGeoPoint *center1 = [[KiiGeoPoint alloc] initWithLatitude:35.658603
                                                    andLongitude:139.745433];
    KiiClause *clause1 = [KiiClause geoDistance:@"location"
                                         center:center1
                                         radius:3000
                                putDistanceInto:@"distance_from_center1"];
    
    // Define the second GeoDistance clause.
    KiiGeoPoint *center2 = [[KiiGeoPoint alloc] initWithLatitude:35.681382
                                                    andLongitude:139.766084];
    KiiClause *clause2 = [KiiClause geoDistance:@"location"
                                         center:center2
                                         radius:3000
                                putDistanceInto:nil];
    
    // Create a query with the GeoDistance clauses and set the sort order.
    KiiClause *totalClause = [KiiClause andClauses:@[clause1, clause2]];
    KiiQuery *query = [KiiQuery queryWithClause:totalClause];
    [query sortByAsc:@"_calculated.distance_from_center1"];
    
    // Create an array for storing all returned KiiObjects.
    NSMutableArray *allResults = [NSMutableArray array];
    
    // Query KiiObjects.
    [bucket executeQuery:query
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      // Add the KiiObjects returned by this query to the "allResults" array.
      [allResults addObjectsFromArray:results];
    
      // Get the distance from the center to the location.
      KiiObject *retObj = [allResults objectAtIndex:0];
      KiiGeoPoint *retPoint = [retObj getGeoPointForKey:@"location"];
      NSDictionary* calc = [retObj getObjectForKey:@"_calculated"];
      NSDecimalNumber *distance = [calc objectForKey:@"distance_from_center1"];
    }];

Here is what is happening in the sample code:

  • Defines two GeoDistance query conditions by calling the geoDistance(_:center:radius:putDistanceInto:) method. Here we specify a GeoPoint representing the center, a radius in meters, and optionally a field that stores the distance between the center of the circular area and a returned KiiObject. Kii Cloud will use this field in a query response.
  • Creates a KiiClause instance by concatenating two GeoDistance query conditions via the andClauses(_:) method. Then creates a KiiQuery instance using this KiiClause instance.
  • Calls the sort(byAsc:) method of the KiiQuery instance to set the sort order.
  • Queries KiiObjects by calling the execute(_:_:) method of the target bucket by passing the query instance.
  • Parses the query results (In this sample, we are appending all returned KiiObjects onto allResults).

With a GeoDistance query condition, Kii Cloud can return the distance between the center point of a GeoPoint and each returned KiiObject. In this example, the distance between GeoDistance1's center point and KiiObjects are returned.

  • The distance will be stored in the field specified when the getDistance(_:center:radius:putDistanceInto:) method is called (the "distance_from_center1" field in this example).
  • To sort query results by distance, call the sort(byAsc:) method with a string "_calculated." followed by the name of the distance field.
  • To get the distance, get the value of the "_calculated" field by calling the getObject(forKey:) method, and then call the object(forKey:) method of the distance field.

Querying with predefined keys

Now, let us show an example of querying with predefined keys.

The next sample code gets KiiObjects that are owned by the current user and are either not updated after creation or updated within a day.

Swift 3:

  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Get values to use in query conditions.
    let userId = KiiUser.current()!.userID!
    let withinOneDay : Int64 = Int64(Date().timeIntervalSince1970 - 24 * 60 * 60) * 1000
    
    // Define clauses with predefined keys and the query conditions.
    let clause1 = KiiClause.equals("_owner", value: userId)
    let clause2 = KiiClause.equals("_version", value: NSNumber(value: 1 as Int))
    let clause3 = KiiClause.equals("_created", value: NSNumber(value: withinOneDay as Int64))
    
    // Define an And clause with the above clauses.
    let totalClause = KiiClause.andClauses([clause1, clause2, clause3])
    
    // Create a query with the And clause.
    let query = KiiQuery(clause: totalClause)
    
    // Define how to output the query result.
    query.sort(byAsc: "_created")
    query.limit = 10
    
    // Create a placeholder for any paginated queries.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      let results = try bucket.executeQuerySynchronous(query, nextQuery: &nextQuery)
      // Do something with the result.
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Get values to use in query conditions.
    let userId = KiiUser.current()!.userID!
    let withinOneDay : Int64 = Int64(Date().timeIntervalSince1970 - 24 * 60 * 60) * 1000
    
    // Define clauses with predefined keys and the query conditions.
    let clause1 = KiiClause.equals("_owner", value: userId)
    let clause2 = KiiClause.equals("_version", value: NSNumber(value: 1 as Int))
    let clause3 = KiiClause.equals("_created", value: NSNumber(value: withinOneDay as Int64))
    
    // Define an And clause with the above clauses.
    let totalClause = KiiClause.andClauses([clause1, clause2, clause3])
    
    // Create a query with the And clause.
    let query = KiiQuery(clause: totalClause)
    
    // Define how to output the query result.
    query.sort(byAsc: "_created")
    query.limit = 10
    
    // Query KiiObjects.
    bucket.execute(query) { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Do something with the result.
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Get values to use in query conditions.
    NSString* userId = [[KiiUser currentUser] userID];
    long long withinOneDay = (long long) (([[NSDate date] timeIntervalSince1970] - 24 * 60 * 60) * 1000);
    
    // Define clauses with predefined keys and the query conditions.
    KiiClause *clause1 = [KiiClause equals:@"_owner"
                                     value:userId];
    KiiClause *clause2 = [KiiClause equals:@"_version"
                                     value:[NSNumber numberWithInt:1]];
    KiiClause *clause3 = [KiiClause greaterThan:@"_created"
                                          value:[NSNumber numberWithLongLong:withinOneDay]];
    
    // Define an And clause with the above clauses.
    KiiClause *totalClause = [KiiClause andClauses:@[clause1,
                                                     [KiiClause orClauses:@[clause2,
                                                                            clause3]]]];
    
    // Create a query with the And clause.
    KiiQuery *query = [KiiQuery queryWithClause:totalClause];
    
    // Define how to output the query result.
    [query sortByAsc:@"_created"];
    [query setLimit:10];
    
    // Create a placeholder for any paginated queries.
    KiiQuery *nextQuery = nil;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:allQuery
                                             withError:&error
                                               andNext:&nextQuery];
    if (error != nil) {
      // Handle the error.
      return;
    }
    // Do something with the result.
     
  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Get values to use in query conditions.
    NSString* userId = [[KiiUser currentUser] userID];
    long long withinOneDay = (long long) (([[NSDate date] timeIntervalSince1970] - 24 * 60 * 60) * 1000);
    
    // Define clauses with predefined keys and the query conditions.
    KiiClause *clause1 = [KiiClause equals:@"_owner"
                                     value:userId];
    KiiClause *clause2 = [KiiClause equals:@"_version"
                                     value:[NSNumber numberWithInt:1]];
    KiiClause *clause3 = [KiiClause greaterThan:@"_created"
                                          value:[NSNumber numberWithLongLong:withinOneDay]];
    
    // Define an And clause with the above clauses.
    KiiClause *totalClause = [KiiClause andClauses:@[clause1,
                                                     [KiiClause orClauses:@[clause2,
                                                                            clause3]]]];
    
    // Create a query with the And clause.
    KiiQuery *query = [KiiQuery queryWithClause:totalClause];
    
    // Define how to output the query result.
    [query sortByAsc:@"_created"];
    [query setLimit:10];
    
    // Query KiiObjects.
    [bucket executeQuery:allQuery
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      // Do something with the result.
    }];

Querying with a specific field name and a field type

Now, let us show an example of querying with a specific field name and a field type. KiiObjects can have various custom fields that are not always consistent. By using a hasField(_:andType:) clause, we can narrow the results to KiiObjects that have a specific field of a specific data type.

The next sample code gets KiiObjects that have an optional promotionalCode field.

Swift 3:

  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Create a clause with a specific field and a type.
    let hasFieldClause = KiiClause.hasField("promotionalCode", fieldType: .String)
    
    // Create a query with the above clause.
    let hasFieldQuery = KiiQuery(clause: hasFieldClause)
    
    // Create a placeholder for any paginated queries.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      let results = try bucket.executeQuerySynchronous(hasFieldQuery, nextQuery: &nextQuery)
      // Do something with the result.
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Prepare the target bucket to be queried.
    let bucket = Kii.bucket(withName: "AppBucket")
    
    // Create a clause with a specific field and a type.
    let hasFieldClause = KiiClause.hasField("promotionalCode", fieldType: .String)
    
    // Create a query with the above clause.
    let hasFieldQuery = KiiQuery(clause: hasFieldClause)
    
    // Query KiiObjects.
    bucket.execute(hasFieldQuery) { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Do something with the result.
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Create a clause with a specific field and a type.
    KiiClause *hasFieldclause = [KiiClause hasField:@"promotionalCode"
                                     fieldType:KiiFieldTypeString];
    
    // Create a query with the above clause.
    KiiQuery *hasFieldQuery = [KiiQuery queryWithClause:hasFieldclause];
    
    // Create a placeholder for any paginated queries.
    KiiQuery *nextQuery;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:hasFieldQuery
                                             withError:&error
                                               andNext:&nextQuery];
    if (error != nil) {
      // Handle the error.
      return;
    }
    // Do something with the result.
     
  • // Prepare the target bucket to be queried.
    KiiBucket *bucket = [Kii bucketWithName:@"AppBucket"];
    
    // Create a clause with a specific field and a type.
    KiiClause *hasFieldClause = [KiiClause hasField:@"promotionalCode"
                                     fieldType:KiiFieldTypeString];
    
    // Create a query with the above clause.
    KiiQuery *hasFieldQuery = [KiiQuery queryWithClause:hasFieldClause];
    
    // Query KiiObjects.
    [bucket executeQuery:hasFieldQuery
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      // Do something with the result.
    }];

Querying with a not clause

Now, let us show an example of querying with a not() clause. This time, we will query KiiObjects that are outside a specified rectangle area.

Swift 3:

  • // Prepare the target bucket to be queried.
    let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Define a GeoBox clause with northeast and southwest points.
    let sw = KiiGeoPoint(latitude: 35.658603, andLongitude: 139.745433)
    let ne = KiiGeoPoint(latitude: 36.069082, andLongitude: 140.07843)
    let notInTheBoxClause = KiiClause.geoBox("location", northEast: sw, southWest: ne)
    
    // Define a not clause with the Geobox clause.
    let notInTheBoxClause = KiiClause.notClause(geoBoxClause)
    
    // Create a query with the Not clause.
    let query = KiiQuery(clause: notInTheBoxClause)
    
    // Create a placeholder for any paginated queries.
    var nextQuery : KiiQuery?
    
    do{
      // Query KiiObjects.
      let results = try bucket.executeQuerySynchronous(query, nextQuery: &nextQuery)
      // Do something with the result.
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Prepare the target bucket to be queried.
    let user = KiiUser.current()!
    let bucket = user.bucket(withName: "MyBucket")
    
    // Define a GeoBox clause with northeast and southwest points.
    let sw = KiiGeoPoint(latitude: 35.658603, andLongitude: 139.745433)
    let ne = KiiGeoPoint(latitude: 36.069082, andLongitude: 140.07843)
    let notInTheBoxClause = KiiClause.geoBox("location", northEast: sw, southWest: ne)
    
    // Define a Not clause with the Geobox clause.
    let notInTheBoxClause = KiiClause.notClause(geoBoxClause)
    
    // Create a query with the Not clause.
    let query = KiiQuery(clause: notInTheBoxClause)
    
    // Query KiiObjects.
    bucket.execute(query) { (query : KiiQuery?, bucket : KiiBucket, results : [Any]?, nextQuery : KiiQuery?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
      // Do something with the result.
    }

Objective-C:

  • NSError *error = nil;
    
    // Prepare the target bucket to be queried.
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Define a GeoBox clause with northeast and southwest points.
    KiiGeoPoint *sw = [[KiiGeoPoint alloc] initWithLatitude:35.52105
                                               andLongitude:139.699402];
    KiiGeoPoint *ne = [[KiiGeoPoint alloc] initWithLatitude:36.069082
                                               andLongitude:140.07843];
    KiiClause *geoBoxclause = [KiiClause geoBox:@"location"
                               northEast:ne
                               southWest:sw];
    
    // Define a not clause with the Geobox clause.
    KiiClause *notInTheBoxClause = [KiiClause notClause:geoBoxclause];
    
    // Create a query with the Not clause.
    KiiQuery *query = [KiiQuery queryWithClause:notInTheBoxClause];
    
    // Create a placeholder for any paginated queries.
    KiiQuery *next = nil;
    
    // Query KiiObjects.
    NSArray *results = [bucket executeQuerySynchronous:query
                                             withError:&error
                                               andNext:&next];
    if (error != nil) {
      // Handle the error.
      return;
    }
    // Do something with the result.
     
  • // Prepare the target bucket to be queried.
    KiiUser *user = [KiiUser currentUser];
    KiiBucket *bucket = [user bucketWithName:@"MyBucket"];
    
    // Define a GeoBox clause with northeast and southwest points.
    KiiGeoPoint *sw = [[KiiGeoPoint alloc] initWithLatitude:35.52105
                                               andLongitude:139.699402];
    KiiGeoPoint *ne = [[KiiGeoPoint alloc] initWithLatitude:36.069082
                                               andLongitude:140.07843];
    KiiClause *geoBoxclause = [KiiClause geoBox:@"location"
                                northEast:ne
                                southWest:sw];
    
    // Define a not clause with the Geobox clause.
    KiiClause *notInTheBoxClause = [KiiClause notClause:geoBoxclause];
    
    // Create a query with the Not clause.
    KiiQuery *query = [KiiQuery queryWithClause:notInTheBoxClause];
    
    // Query KiiObjects.
    [bucket executeQuery:query
               withBlock:^(KiiQuery *query, KiiBucket *bucket, NSArray *results, KiiQuery *nextQuery, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      // Do something with the result.
    }];

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.