Single Property Indexを作らないとComposite Indexも作成されない?
昨日行われたappengine ja night #9で話題になった次の二つについて試してみました。
- プロパティa、bに対してSingle Property Indexは作らずにComposite Indexだけを作った場合、a=1、b=2、c=3のようなフィルタを使えばComposite Index + ZigZag Scanを試せるんじゃないか。
- プロパティa、bに対してSingle Property Indexは作らずにComposite Indexだけを作った場合、a=1のようなaだけを使ったフィルタは機能するか。
結果
Single Property Indexを作らなかったEntityは、Composite Indexテーブルに登録されないように見えます。下記コードの三つのQueryの結果はすべて空でした。Entity#setUnindexedPropertyメソッドを利用した場合は、Composite Indexも含めてIndexテーブルに書き込む処理が省略されているのかもしれません。
実行結果はこちら。何も出てこないのでまったく面白くないですがw
ソース
package org.koherent.appengine.ajn9; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import javax.servlet.http.*; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Query; import com.google.appengine.api.datastore.Query.FilterOperator; @SuppressWarnings("serial") public class CompositeIndexTestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/plain"); response.setCharacterEncoding("UTF-8"); DatastoreService datastore = DatastoreServiceFactory .getDatastoreService(); List<Entity> entities = new ArrayList<Entity>(); Entity entity; Query query; Iterable<Entity> results; PrintWriter out = response.getWriter(); ////////////////////////////////////////////////////////////// // (0) Preparation: Puts entities // (The composite index for "a" and "b" exists) entity = new Entity("kind", "keyName1"); entity.setUnindexedProperty("a", 1); // propertyName = "a", value = 1 entity.setUnindexedProperty("b", 1); entity.setProperty("c", 3); entities.add(entity); entity = new Entity("kind", "keyName2"); entity.setUnindexedProperty("a", 1); entity.setUnindexedProperty("b", 2); entity.setProperty("c", 3); entities.add(entity); entity = new Entity("kind", "keyName3"); entity.setUnindexedProperty("a", 2); entity.setUnindexedProperty("b", 2); entity.setProperty("c", 3); entities.add(entity); datastore.put(entities); ////////////////////////////////////////////////////////////// // (1) Combinations of the composite index and zigzag scan query = new Query("kind"); query.addFilter("a", FilterOperator.EQUAL, 1); // composite index query.addFilter("b", FilterOperator.EQUAL, 2); // composite index query.addFilter("c", FilterOperator.EQUAL, 3); // zigzag scan results = datastore.prepare(query).asIterable(); for (Entity result : results) { out.print("(1) "); out.println(result.getKey().getName()); // keyName2 } ////////////////////////////////////////////////////////////// // (2) Filtering by the first property of the composite index query = new Query("kind").addFilter("a", FilterOperator.EQUAL, 2); results = datastore.prepare(query).asIterable(); for (Entity result : results) { out.print("(2) "); out.println(result.getKey().getName()); // keyName3 } ////////////////////////////////////////////////////////////// // (3) Must use the composite index query = new Query("kind"); query.addFilter("a", FilterOperator.EQUAL, 2); query.addFilter("b", FilterOperator.GREATER_THAN_OR_EQUAL, Long.MIN_VALUE); query.addFilter("b", FilterOperator.LESS_THAN_OR_EQUAL, Long.MAX_VALUE); results = datastore.prepare(query).asIterable(); for (Entity result : results) { out.print("(3) "); out.println(result.getKey().getName()); // keyName3 } } }
<?xml version="1.0" encoding="utf-8"?> <datastore-indexes> <datastore-index kind="kind" ancestor="false"> <property name="a" direction="asc" /> <property name="b" direction="asc" /> </datastore-index> </datastore-indexes>
補足
最初からEntity#setUnindexedPropertyメソッドを使うとそもそもComposite Indexが作成すらされなかったので、一度Entity#setPropertyメソッドを使ってComposite Indexを作成させてから上記のコードに差し替えました。
当然ですが、Entity#setPropertyを使った場合は次のような結果になりました。
(1) keyName2
(2) keyName3
(3) keyName3