KiiObject の検索

Kii Cloud の Bucket 内 KiiObject の取得には、条件を指定した検索が使用できます。たとえば「Bucket より "count" フィールドの値が 10 より大きい KiiObject を、フィールド値降順で最大で 10 個取得」などといった条件に基づく KiiObject の取得が可能です。

さまざまな検索の例については、検索のサンプルコード を参照してください。

KiiObject 検索の実行

検索条件の指定

個々の検索条件は、KiiClause の以下のメソッドを用いて定義します。

メソッド 定義される検索条件
equals(_:value:) フィールド値が、指定の値に等しい場合にマッチ。
notEquals(_:value:) フィールド値が、指定の値に等しくない場合にマッチ。ただし指定したフィールド自体が存在しない場合はマッチしません。
greaterThan(_:value:) フィールド値が、指定の値より大きい場合にマッチ。
greaterThanOrEqual(_:value:) フィールド値が、指定の値以上の場合にマッチ。
lessThan(_:value:) フィールド値が、指定の値より小さい場合にマッチ。
lessThanOrEqual(_:value:) フィールド値が、指定の値以下の場合にマッチ。
in(_:value:) フィールド値が、指定の値のいずれかを持っている場合にマッチ。最大 200 件まで指定可能。JSON のフィールド型との一致が必要。
startsWith(_:value:) フィールド値(String 型)が、指定の文字列により始まっている場合にマッチ。
geoBox(_:northEast:southWest:) フィールド値(GeoPoint 型)が、指定の GeoBox(長方形エリア)の中に含まれる場合にマッチ。
geoDistance(_:center:radius:putDistanceInto:) フィールド値(GeoPoint 型)が、指定の GeoDistance(円エリア)の中に含まれる場合にマッチ。
hasField(_:andType:) フィールドが、指定の型である場合にマッチ。現在サポートされている型は KiiFieldTypeStringKiiFieldTypeIntegerKiiFieldTypeDecimal、および KiiFieldTypeBoolean です。

また複数の条件を結合するメソッドとして、次のものが利用可能です。

メソッド 定義される検索条件
andClauses(_:) 複数の検索条件を AND で結合。
orClauses(_:) 複数の検索条件を OR で結合。
notClause(_:) 複数の検索条件を NOT で結合。引数は KiiClause インスタンスで、単一条件の句か、andClauses(_:) または orClauses(_:) メソッドで結合した複数条件の句です。

KiiClause クラスの詳細は appledoc を参照してください。

notClause(_:) を含むクエリーでは、パフォーマンスが低下することがありますが、式の変形によって notClause(_:) の使用を回避できる場合があります。詳細は Not を含む式の変形 を参照してください。

クエリインスタンスの作成と検索の実行

検索を実行するには、まずクエリインスタンスを作成します。これは、検索条件を指定した KiiClause インスタンスを指定して KiiQuery インスタンスを作成することにより行います。KiiClause インスタンスを指定せずに KiiQuery インスタンスを作成した場合は、対象 Bucket 内の全ての KiiObject がマッチするクエリインスタンスが作成されます(i.e. all 検索に相当)

KiiQuery インスタンス作成後、さらにオプションとして以下のメソッドおよびプロパティを用いて検索結果のソート順指定や、一度に受け取る検索結果の件数上限を設定できます。

  • sortByAsc(_:):指定フィールドをキーに昇順ソート。
  • sortByDesc(_:):指定フィールドをキーに降順ソート。
  • limit:一度に返す検索結果の最大アイテム数(Best Effort の値)。最大値は 200。

クエリの詳細な仕様は以下のとおりです。

  • 検索結果のソートには 1 フィールドのみを指定できます。

  • sortByAsc(_:) メソッドと sortByDesc(_:) メソッドのどちらも指定しない場合、検索結果のソート順は不定となります。limit プロパティを指定しない場合、一度の検索で受け取れる最大アイテム数は 200 となります。

  • パフォーマンスの最適化のため、指定した最大アイテム数 ≦ クエリにマッチする全件数 のとき、実際に返却される件数 = 指定した最大アイテム数となることが保証されません。最大アイテム数分、存在していることが分かっていても、取得できた件数の確認は必要です。

  • 200 件以上取得する場合は、下記に示す ページネーション を利用して、複数回に分割して取得します。

  • sortByAsc(_:) メソッドと sortByDesc(_:) メソッドによるソートは、整数のフィールドはその値の大小で、文字列のフィールドは辞書順で行われます。

  • 格納されているフィールドの型が KiiObject によって異なると正しく検索やソートができません。

  • 文字列のフィールドでは、値の大文字と小文字を区別して検索します。たとえば、クエリーの値 "alice" で、KiiObject の格納値 "Alice" を検索してもヒットしません。

  • 実数のフィールドでは、検索やソートが期待どおりに実行されない場合があります。実数のうち、小数点以下が 0 の値は整数として扱われます。例えば、1.0 は整数 1 として、1.1 は と実数 1.1 として、それぞれ異なる型でインデックスされます。これら、異なる型の間では大小関係が正しく評価されないため、期待した結果が得られません。実数での検索やソートを行いたい場合は、元の値を 10 倍、100 倍するなどして整数化したフィールドを保存し、そのフィールドを使ってクエリーを実行してください。

  • 検索対象となるフィールドは、KiiObject の JSON 表現の第 1 階層だけです。ネストした KiiObject のフィールドはインデックスされないため、深い階層にあるフィールドを検索してもヒットしません。

  • in(_:value:) メソッドを使う場合は、NSArray の各要素の型が KiiObject に格納されている JSON の型と一致する点を確認してください。たとえば、{"id" : 123} は文字列が格納された NSArray ではマッチせず、数値の NSArray を指定しないと結果が得られません。NSArray で float や double を扱う場合、各要素で小数を含む値と含まない値を混在させた検索はできません。

  • フィールド名は 250 文字まで、String 型の値は 190 文字まで検索できます。これらを超える長さのフィールド名や値を持つキーと値のペアは、このフィールドで検索してもヒットしません。

検索の実行は、作成したクエリインスタンスを指定して、検索対象 Bucket の execute(_:_:) メソッドを実行することで行います。

KiiQuery クラスの詳細は appledoc を参照してください。

KiiObject 数が多くなる場合、クエリーやソートによってパフォーマンスが低下する場合があります。対処方法のヒントは パフォーマンス をご覧ください。

検索における所定キーの使用

キーと値のペアとしてアプリから作成したデータ以外に、Kii Cloud によって自動的に生成された所定キー による検索もできます。

所定キーには、KiiObject の ID や作成日時などの様々なフィールドがあります。所定キーの一覧は、所定キー を参照してください。

KiiObject 検索結果の取得

検索結果は NSArray で返されます。各要素は KiiObject です。一度に全ての KiiObject が取得できなかった場合(たとえば、limit に 10 を指定し、検索結果は 30 件だった場合)、KiiQuery インスタンスが同時に返されます。この KiiQuery インスタンスを用いて再度検索行うことで、残りの KiiObject を取得できます。

ただし、サーバーから 1 回で返される件数とクエリ条件にマッチする件数が等しく、未取得の検索結果が存在しない場合に、SDK から未取得の結果が存在すると返される(nextQuery != nil になる)可能性があります。次のページの取得時に、空の結果が取得されうることを前提にした実装が必要です。

Web のように一定件数ずつページングするような画面構成を実現したい場合、ページの管理は自分で行う必要があります。検索結果は、順方向にのみ取得でき、かつ、1 回の取得件数は Best Effort のため一定しません。先に KiiObject の件数 を取得して、ページ管理に使用することもできます。