検索のサンプルコード

さまざまな検索の例を以下に示します。

Bucket 内の全 Object の取得

まずは、もっとも単純な検索として Bucket 内の全ての Object を取得する例について説明します。

  • // Create a query that returns all KiiObjects.
    KiiQuery all_query = new KiiQuery();
    
    try {
     // Query KiiObjects.
      KiiQueryResult<KiiObject> result = Kii.bucket("AppBucket")
              .query(all_query);
      // Alternatively, you can use:
      // KiiQueryResult<KiiObject> result = Kii.bucket("AppBucket")
      //         .query(null);
    
      List<KiiObject> objLists = result.getResult();
      for (KiiObject obj : objLists) {
        // Do something with KiiObjects in the result.
      }
    } catch (IOException e) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Create a query that returns all KiiObjects.
    KiiQuery all_query = new KiiQuery();
    
    // Query KiiObjects.
    Kii.bucket("AppBucket")
      .query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        List<KiiObject> objLists = result.getResult();
        for (KiiObject obj : objLists) {
          // Do something with KiiObjects in the result.
        }
      }
    }, all_query);
    // Alternatively, you can use:
    // Kii.bucket("AppBucket")
    //         .query(..., null);

ここでは以下の処理が行われています。

  • KiiClause を何も指定せずに KiiQuery インスタンスを作成し、"all" 検索用のクエリインスタンスを作成。
  • このクエリインスタンスを、検索対象 Bucket の query メソッドに渡して実行。別の方法として、query() メソッドを null 指定で実行することもできます。
  • KiiQueryResult として返却された検索結果を getResult() メソッドを用いてパース。

Bucket に対して "all" 検索を実施しているため、検索結果には Bucket 内の全ての Object が含まれます。

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

複数条件の検索

次に、以下の条件で検索を実行する例を取り上げます。

  • "gender" フィールドの値が "Female"、かつ "age" フィールドの値が 18 より大きい
  • "age" フィールドの昇順で検索結果をソート。
  • 一度の検索実行で取得する検索結果の最大件数を 10 件に設定。
  • // Prepare the target bucket to be queried.
    KiiBucket bucket = Kii.bucket("AppBucket");
    
    // Create a query with clauses.
    KiiQuery query = new KiiQuery(KiiClause.and(
            KiiClause.equals("gender", "Female"),
            KiiClause.greaterThan("age", 18)));
    
    // Define how to output the query result.
    query.sortByAsc("age");
    query.setLimit(10);
    
    try {
      // Query KiiObjects.
      KiiQueryResult<KiiObject> result = bucket.query(query);
      List<KiiObject> objLists = result.getResult();
      for (KiiObject obj : objLists) {
        // Do something with the first 10 KiiObjects.
      }
    
      // If there is more data to retrieve
      while (result.hasNext()) {
        // Query the next 10 KiiObjects with pagination.
        result = result.getNextQueryResult();
        objLists = result.getResult();
        for (KiiObject obj : objLists) {
          // Do something with the next 10 KiiObjects.
        }
      }
    } catch (IOException e) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Prepare the target bucket to be queried.
    KiiBucket bucket = Kii.bucket("AppBucket");
    
    // Create a query with clauses.
    KiiQuery query = new KiiQuery(KiiClause.and(
            KiiClause.equals("gender", "Female"),
            KiiClause.greaterThan("age", 18)));
    
    // Define how to output the query result.
    query.sortByAsc("age");
    query.setLimit(10);
    
    // Query KiiObjects.
    bucket.query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        List<KiiObject> objLists = result.getResult();
        for (KiiObject obj : objLists) {
          // Do something with the first 10 KiiObjects.
        }
    
        // If there is more data to retrieve
        if (!result.hasNext()) {
          return;
        }
        // Query the next 10 KiiObjects with pagination.
        result.getNextQueryResult(this);
      }
    }, query);

ここでは以下の処理が行われています。

  • equals() メソッドと greaterThan() メソッドを用いて個々の検索条件を定義。さらにこれらの検索条件を and() メソッドで結合した KiiClause インスタンスを用いて KiiQuery インスタンスを作成。
  • KiiQuery インスタンスの sortByAsc() メソッドを実行して、ソート順序を指定。
  • KiiQuery インスタンスの setLimit() メソッドを実行して、一度に取得する検索結果の最大件数を指定。
  • KiiQuery インスタンスを指定して検索対象 Bucket の query() メソッドを実行し、検索を実施。
  • KiiQueryResult インスタンスとして返却された検索結果を getResult() メソッドを用いてパース。

今回の例では、ページネーションを考慮した検索結果のパースを行っています。

  • 検索結果のパース終了後、KiiQueryResult インスタンスの hasNext() メソッドを実行して、未取得の検索結果が存在するか確認。
  • もし未取得の検索結果が存在する場合は、getNextQueryResult() メソッドを実行して、次の検索結果 10 件を含む KiiQueryResult インスタンスを取得。

位置情報による検索

次に、位置情報に基づく Object 検索を行う例を挙げます。

まず、以下のように "location" というフィールドに GeoPoint を持つ Object が存在するものとします。

  • KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    // Create a KiiObject.
    KiiObject object = bucket.object();
    GeoPoint point = new GeoPoint(35.661561, 139.769595);
    object.set("location", point);
    try {
      // Save the KiiObject.
      object.save();
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    // Create a KiiObject.
    KiiObject object = bucket.object();
    GeoPoint point = new GeoPoint(35.677379, 139.702148);
    object.set("location", point);
    
    // Save the KiiObject.
    object.save(new KiiObjectCallBack() {
      @Override
      public void onSaveCompleted(int token, KiiObject object, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
      }
    });

GeoBox(長方形エリア)による Object 検索を行うには、以下の様な処理を行います。

  • // Prepare the target bucket to be queried.
    KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    try {
      // Define a GeoBox clause with northeast and southwest points.
      GeoPoint sw = new GeoPoint(35.52105, 139.699402);
      GeoPoint ne = new GeoPoint(36.069082, 140.07843);
      KiiClause clause = KiiClause.geoBox("location", ne, sw);
    
      // Create a query with the GeoBox clause.
      KiiQuery query = new KiiQuery(clause);
    
      // Query KiiObjects.
      KiiQueryResult<KiiObject> result = bucket.query(query);
    
      // Do something with the result.
    
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Prepare the target bucket to be queried.
    KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    // Define a GeoBox clause with northeast and southwest points.
    GeoPoint sw = new GeoPoint(35.52105, 139.699402);
    GeoPoint ne = new GeoPoint(36.069082, 140.07843);
    KiiClause clause = KiiClause.geoBox("location", ne, sw);
    
    // Create a query with the GeoBox clause.
    KiiQuery query = new KiiQuery(clause);
    
    // Query KiiObjects.
    bucket.query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        // Do something with the result.
      }
    }, query);

この例のように、GeoBox の検索条件は北東点と南西点を表す GeoPoint を指定して geoBox() メソッドを実行することにより定義します。

次に、GeoDistance(円エリア)による Object 検索を行う処理例を以下に示します。この例では 2 つの GeoDistance を定義しており、これら 2 つの GeoDistance が交わるエリアにマッチする Object を検索しています。また、検索結果を片方の GeoDistance の中心点より近い順にソートしています。

  • // Prepare the target bucket to be queried.
    KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    try {
      // Define the first GeoDistance clause.
      String distanceField1 = "distance_from_center1";
      GeoPoint center1 = new GeoPoint(35.658603, 139.745433);
      KiiClause clause1 = KiiClause.geoDistance("location", center1,
              3000, distanceField1);
    
      // Define the second GeoDistance clause.
      GeoPoint center2 = new GeoPoint(35.681382, 139.766084);
      KiiClause clause2 = KiiClause.geoDistance("location", center2, 3000, null);
    
      // Create a query with the GeoDistance clauses and set the sort order.
      KiiQuery query = new KiiQuery(KiiClause.and(clause1, clause2));
      String sortKey = "_calculated." + distanceField1;
      query.sortByAsc(sortKey);
    
      // Query KiiObjects.
      KiiQueryResult<KiiObject> result = bucket.query(query);
    
      // Do something with the result.
      // This example just fetches the first KiiObject.
      List<KiiObject> objects = result.getResult();
      KiiObject objInquired = objects.get(0);
    
      // Get the distance from the center to the location.
      double distance = objInquired.getJSONObject("_calculated")
            .getDouble(distanceField1);
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    } catch (JSONException jse) {
      // Handle the error.
    }
  • // Prepare the target bucket to be queried.
    KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    // Define the first GeoDistance clause.
    final String distanceField1 = "distance_from_center1";
    GeoPoint center1 = new GeoPoint(35.658603, 139.745433);
    KiiClause clause1 = KiiClause.geoDistance("location", center1,
            3000, distanceField1);
    
    // Define the second GeoDistance clause.
    GeoPoint center2 = new GeoPoint(35.681382, 139.766084);
    KiiClause clause2 = KiiClause.geoDistance("location", center2, 3000, null);
    
    // Create a query with the GeoDistance clauses and set the sort order.
    KiiQuery query = new KiiQuery(KiiClause.and(clause1, clause2));
    String sortKey = "_calculated." + distanceField1;
    query.sortByAsc(sortKey);
    
    // Query KiiObjects.
    bucket.query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        // Do something with the result.
        // This example just fetches the first KiiObject.
        List<KiiObject> objects = result.getResult();
        KiiObject objInquired = objects.get(0);
    
        try {
          // Get the distance from the center to the location.
          double distance = objInquired.getJSONObject("_calculated")
                  .getDouble(distanceField1);
        } catch (JSONException jse) {
          // Handle the error.
        }
      }
    }, query);

ここでは以下の処理が行われています。

  • 中心点を表す GeoPoint、半径(メートル)、中心点からの距離格納用フィールド(オプショナル)を指定して geoDistance() メソッドを実行し、GeoDistance の検索条件を定義。
  • 2 つの GeoDistance を and() メソッドで結合した KiiClause インスタンスを用いて KiiQuery インスタンスを作成。
  • KiiQuery インスタンスの sortByAsc() メソッドを実行して、ソート順序を指定。
  • KiiQuery インスタンスを指定して検索対象 Bucket の query() メソッドを実行し、検索を実施。
  • KiiQueryResult インスタンスとして返却された検索結果を getResult() メソッドを用いてパース。

GeoDistance による検索を行った場合、検索にマッチした Object のそれぞれに対して、中心点からの距離(メートル)を Kii Cloud にセットさせることができます。今回の例では、GeoDistance1 の中心点からの距離を Kii Cloud にセットさせています。

  • 距離は、geoDistance() メソッド実行時に指定した距離格納用フィールドにセットされます。
  • この距離を用いてソートを行う場合は、例のように "_calculated." の後に距離格納用フィールド名をアペンドした文字列を sortByAsc() メソッドに指定します。
  • 検索結果より距離を取得するには、例のように Object の "_calculated" フィールドを getJSONObject() メソッドで取得し、さらに getDouble() メソッドを実行して距離格納用フィールドより距離を取得します。

所定キーによる検索

次に、所定キーを検索条件に使った検索の例を挙げます。

次のコードでは、ログイン中のユーザーによって作成された Object のうち、更新されていないものと 1 日以内に作成されたものの両方を取得する条件で検索しています。ユーザー ID や作成日時はここに示すような方法で比較できます。

  • // Prepare the target bucket to be queried.
    KiiBucket bucket = Kii.bucket("AppBucket");
    
    // Get values to use in query conditions.
    String userId = KiiUser.getCurrentUser().toUri().getLastPathSegment();
    long withinOneDay = System.currentTimeMillis() - 24 * 60 * 60 * 1000;
    
    // Create a query with clauses using predefined keys and the retrieved values.
    KiiQuery query = new KiiQuery(KiiClause.and(
        KiiClause.equals("_owner", userId),
        KiiClause.or(
            KiiClause.equals("_version", 1),
            KiiClause.greaterThan("_created", withinOneDay))));
    
    // Define how to output the query result.
    query.sortByAsc("_created");
    query.setLimit(10);
    
    try {
      // Query KiiObjects.
      KiiQueryResult<KiiObject> result = bucket.query(query);
      List<KiiObject> objLists = result.getResult();
      for (KiiObject obj : objLists) {
        // Do something with the first 10 KiiObjects.
      }
    } catch (IOException e) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Prepare the target bucket to be queried.
    KiiBucket bucket = Kii.bucket("AppBucket");
    
    // Get values to use in query conditions.
    String userId = KiiUser.getCurrentUser().getID();
    long withinOneDay = System.currentTimeMillis() - 24 * 60 * 60 * 1000;
    
    // Create a query with clauses using predefined keys and the retrieved values.
    KiiQuery query = new KiiQuery(KiiClause.and(
        KiiClause.equals("_owner", userId),
        KiiClause.or(
            KiiClause.equals("_version", 1),
            KiiClause.greaterThan("_created", withinOneDay))));
    
    // Define how to output the query result.
    query.sortByAsc("_created");
    query.setLimit(10);
    
    // Query KiiObjects.
    bucket.query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        List<KiiObject> objLists = result.getResult();
        for (KiiObject obj : objLists) {
          // Do something with the first 10 KiiObjects.
        }
      }
    }, query);

特定のフィールド名および型による検索

特定のフィールド名および型を指定した検索の例を挙げます。Object にはさまざまなカスタムフィールドを持たせることができ、名前と型が必ずしも一様ではなくなる可能性があります。hasField 句で検索対象を絞り込み、特定の型のフィールドを持つ Object のみを取得できます。

次のサンプルコードでは、省略可能な promotionalCode フィールドを持つ Object のみを取得します。

  • // Create a query with a clause using a specific field and a type.
    KiiQuery hasField_query = new KiiQuery(KiiClause.hasField("promotionalCode",FieldType.String));
    
    try {
      // Query KiiObjects.
      KiiQueryResult<KiiObject> result = Kii.bucket("AppBucket")
              .query(hasField_query);
    
      List<KiiObject> objLists = result.getResult();
      for (KiiObject obj : objLists) {
        // Do something with KiiObjects in the result.
      }
    } catch (IOException e) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Create a query with a clause using a specific field and a type.
    KiiQuery hasField_query = new KiiQuery(KiiClause.hasField("promotionalCode",FieldType.String));
    
    // Query KiiObjects.
    Kii.bucket("AppBucket")
      .query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        List<KiiObject> objLists = result.getResult();
        for (KiiObject obj : objLists) {
          // Do something with KiiObjects in the result.
        }
      }
    }, hasField_query);

Not 句による検索

Not 句による検索の例を挙げます。長方形のエリアを指定して、その外部に位置する Object を検索します。

  • // Prepare the target bucket to be queried.
    KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    try {
      // Define a GeoBox clause with northeast and southwest points.
      GeoPoint sw = new GeoPoint(35.52105, 139.699402);
      GeoPoint ne = new GeoPoint(36.069082, 140.07843);
      KiiClause geoBoxClause = KiiClause.GeoBox("location", ne, sw);
    
      // Define a not clause with the Geobox clause.
      KiiClause notInTheBoxClause = KiiClause.not(geoBoxClause)
    
      // Create a query with the Not clause.
      KiiQuery query = new KiiQuery(notInTheBoxClause);
    
      // Query KiiObjects.
      KiiQueryResult<KiiObject> result = bucket.query(query);
    
      // Do something with the result.
    
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Prepare the target bucket to be queried.
    KiiBucket bucket = KiiUser.getCurrentUser().bucket("myBucket");
    
    // Define a GeoBox clause with northeast and southwest points.
    GeoPoint sw = new GeoPoint(35.52105, 139.699402);
    GeoPoint ne = new GeoPoint(36.069082, 140.07843);
    KiiClause geoBoxClause = KiiClause.GeoBox("location", ne, sw);
    
    // Define a not clause with the Geobox clause.
    KiiClause notInTheBoxClause = KiiClause.not(geoBoxClause)
    
    // Create a query with the Not clause.
    KiiQuery query = new KiiQuery(notInTheBoxClause);
    
    // Query KiiObjects.
    bucket.query(new KiiQueryCallBack<KiiObject>() {
      @Override
      public void onQueryCompleted(int token, KiiQueryResult<KiiObject> result, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        // Do something with the result.
      }
    }, query);

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