KiiObject の検索

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

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

KiiObject を検索するには、次の例のように QueryRequst オブジェクトを Kii Cloud に送信します。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/vnd.kii.QueryRequest+json" \
  "https://api-jp.kii.com/api/apps/{APP_ID}/users/me/buckets/{BUCKET_ID}/query" \
  -d '{
        "bucketQuery": {
          "clause": {
            "type": "eq", "field": "name",
            "value": "John Doe"
          },
          "orderBy": "name", "descending": false
        },
        "bestEffortLimit": 10
      }'

期待どおりに取得できない場合、スコープの違い もご確認ください。

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

Query Requset オブジェクト

Query Request オブジェクトの一例を以下に示します。

{
  "bucketQuery":{
    "clause":{"type": "eq", "field": "name", "value": "John Doe"},
    "orderBy":"name",
    "descending": false
  },
  "paginationKey":"asd12ijdfasdfjadfjgk",
  "bestEffortLimit":10
}
  • "bucketQuery" に検索クエリを指定します。検索クエリは、以下の 3 つの情報により構成されます。
    • "clause" には検索条件を指定します。指定方法は本ページの 検索条件の節を参照してください。
    • "orderBy" と "descending" には検索結果のソート方法を指定します。検索結果は、"orderBy" に指定したフィールドの値を元にソートされます。この際、"descending" が true の場合は降順に、"false" の場合は昇順にソートされます。"descending" が指定されていない場合はデフォルトで降順にソートされます。また "orderBy" が指定されていない場合、ソート順は不定となります。
  • "paginationKey" は、前回のクエリ結果が検索条件を満たす全ての KiiObject を返せなかった際に、次の結果を取得する場合に指定します。詳細は本ページの ページネーション を参照してください。
  • "bestEffortLimit" は、検索結果として最大何件の KiiObject を受け取るかを指定します。指定がない場合はデフォルトで 200 が適用されます。また指定可能な最大値は 200 です。200 件以上取得する場合は、ページネーションを利用して、複数回に分割して取得します。詳細は本ページの ページネーション を参照してください。

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

orderBy によるソートは、整数のフィールドはその値の大小で、文字列のフィールドは辞書順で行われます。

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

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

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

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

検索条件

検索条件は、以下にあげる条件を 1 つまたは複数利用して定義します。

  • EqualClause:フィールド値が、指定の値と等しい場合にマッチ。

    { "type":"eq",  "field":"name",  "value":"John Doe" }
    
  • PrefixClause:フィールド値が、指定の文字列により始まっている場合にマッチ。String 型のデータに対してのみ有効。

    { "type":"prefix",  "field":"name",  "prefix":"John" }
    
  • RangeCluase:フィールド値が、指定の範囲内に収まっている場合にマッチ。

    {
      "type": "range",
      "field" : "age",
      "upperLimit":10,
      "upperIncluded":true,
      "lowerLimit":3,
      "lowerIncluded":false
    }
    

    範囲の指定方法は、以下の例を参考にしてください。

    • age が 20 以上:{ "type":"range", "field":"age", "lowerLimit": 20 }
    • age が 20 より大きい:{ "type":"range", "field":"age", "lowerLimit": 20, "lowerIncluded": false }
    • age が 20 以上、30 未満:{ "type":"range", "field":"age", "lowerLimit": 20, "upperLimit":30, "upperIncluded":false }
  • AllClause:Bucket 内の全ての KiiObject にマッチ。

    { "type": "all" }
    
  • InClause:フィールド値が、指定の値のいずれかを持っている場合にマッチ。最大 200 件まで指定可能。

    {
      "type": "in",
      "field": "lastName",
      "values": [ "Garcia", "Smith", "Lopez", "Simpson" ]
    }
    

    InClause を使う場合は、指定する値の型が KiiObject に格納されている JSON の型と一致する点を確認してください。たとえば、{"id" : 123} は文字列 "123" ではマッチせず、数値 123 を指定しないと結果が得られません。また、値を複数指定する場合は同じ型しか指定できません。クエリに数値と文字列を混在させたり、小数を含む数値と含まない数値を混在させた検索はできません。

  • HasFieldClause:KiiObject が指定のフィールドを持っている場合にマッチ。フィールドのデータ型("STRING"、"INTEGER"、"DECIMAL"、"BOOLEAN")の指定が必要。

    {
      "type": "hasField",
      "field": "name",
      "fieldType": "STRING"
    }
    
  • AndCluase:複数の条件を AND 論理演算子で結合。

    {
      "type": "and",
      "clauses": [
        {"type": "prefix", "field": "name", "prefix": "John"},
        {"type": "eq", "field": "age", "value": 30}
      ]
    }
    
  • OrClause:複数の条件を OR 論理演算子で結合。

    {
      "type": "or",
      "clauses": [
        {"type": "eq", "field": "name", "value": "John"},
        {"type": "eq", "field": "age", "value": 30}
      ]
    }
    
  • NotClause:条件を NOT 論理演算子で否定。

    {
      "type": "not",
      "clause": {"type": "eq", "field": "name", "value": "John"}
    }
    

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

  • GeoBoxClause:GeoPoint が、指定の GeoBox(長方形エリア)の中に入るかを確認。

    GeoBox は、2 点(北東の ne と、南西の sw)により定義されます。以下に例を挙げます。

    {
      "type": "geobox",
      "field": "mylocation",
      "box": {
        "ne": {
          "_type": "point",
          "lat": 11.0,
          "lon": 1.0
        },
          "sw": {
          "_type": "point",
          "lat": 1.0,
          "lon": 17.0
        }
      }
    }
    
  • GeoDistanceClause:GeoPoint が、指定の GeoDistance(円エリア)の中に入るかを確認。

    GeoDistance は、中心点と半径(メートル指定)により定義されます。以下に例を挙げます。

    {
      "type": "geodistance",
      "field": "mylocation",
      "center": {
          "_type": "point",
          "lat": 11.0,
          "lon": 1.0
      }
      "radius": 1023,
      "putDistanceInto": "distance_to_mylocation"
    }
    

    フィールド "putDistanceInto" には、Kii Cloud が検索結果を返す際に、中心点からの距離をどのフィールドに入れるかを指定します。たとえば、上記の検索例の結果は次のようになります。

    ...
    {
      "mylocation": {
        "_type": "point",
        "lat": 11.0,
        "lon": 1.0
      },
      "_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "_modified": 1366965367393,
      "_created": 1366965367393,
      "_owner": "SYS_ADMIN",
      "_version": "1",
      "_calculated": {
        "distance_to_mylocation": 15605.156575746192
      }
    }
    ...
    

    フィールド "_calculated" の中に、指定したフィールド "distance_to_mylocation" が含まれていることがわかります。このフィールドの値は、中心点からの距離(メートル)を表しています。また、このフィールド値でソートを行うこともできます(昇順のみサポート)。

    検索時にフィールド "putDistanceInto" を省略することもできます。この場合は、検索結果にフィールド "_calculated" が含まれません。

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

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

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

ページネーション

QueryRequest オブジェクトの "bestEffortLimit" は、Kii Cloud は検索結果として返す KiiObject の最大件数を決定します。検索結果を満たす KiiObject がこの指定値以上存在した場合、すべての検索結果を一度に取得できません。また、検索条件にマッチする KiiObject が多数存在する場合、これが "bestEffortLimit" で指定した数未満であっても全ての検索結果を一度に返すことができない場合があります。

このような場合、ページネーションキー "paginationKey" を使用して検索を実行します。

初回の検索では、"paginationKey" を指定せずに実行します。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/vnd.kii.QueryRequest+json" \
  "https://api-jp.kii.com/api/apps/{APP_ID}/users/me/buckets/{BUCKET_ID}/query" \
  -d '{
        "bucketQuery": {
          "clause": {
            "type": "all"
          }
        }
      }'

検索結果が一度に返せなかった場合、Kii Cloud は検索結果とともに、以下の例のように "nextPaginationKey" という値を返します。

{
  "queryDescription": "WHERE ( 1=1 )",
  "results": [....],
  "nextPaginationKey": "200/200"
}

この "nextPaginationKey" の値を次回検索時に "paginationKey" として指定すると、未取得の検索結果を受け取ることができます。なお、"nextPaginationKey" はページ指定の文字列のように見えますが、独自の値を与えることはできず、常に直前の検索結果で返されたものを指定します。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/vnd.kii.QueryRequest+json" \
  "https://api-jp.kii.com/api/apps/{APP_ID}/users/me/buckets/{BUCKET_ID}/query" \
  -d '{
        "bucketQuery": {
          "clause": {
            "type": "all"
          }
        },
        "paginationKey": "200/200"
      }'

この検索を実行すると、さらに次の "nextPaginationKey" が検索結果とともに取得できます。同様に、この値を次の検索で指定します。検索結果に "nextPaginationKey" が含まれない場合は、全件の取得が完了したことを意味します。

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

Kii Cloud は検索結果のスナップショットを保持していない点に注意してください。前回検索時より時間が経過した後に未取得分の要求を行った場合、検索結果に食い違いが生じる可能性があります。