如何使用Objectify正确查询Datastore的__Stat_Ns_Kind__统计表?
解决方案
问题根源
你遇到的问题核心在于三点:
- Datastore的
__Stat_Ns_Kind__是系统内置统计实体,Objectify默认不会自动映射这类实体,直接用kind()查询无法正确解析结果; - 该统计实体的索引由Datastore自动维护,不支持自定义复合索引,因此投影查询会触发索引缺失报错;
- 若未指定
namespace_name过滤,即使GQL能查到结果,Objectify查询也可能因命名空间不匹配返回null。
方案1:创建映射实体类查询
先定义与__Stat_Ns_Kind__字段匹配的实体类,明确指定实体kind名称:
import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; @Entity(name = "__Stat_Ns_Kind__") public class StatNsKind { @Id private Long id; private String kind_name; private Long count; private String namespace_name; // Objectify要求必须有无参构造函数 public StatNsKind() {} // 按需实现Getter方法 public Long getCount() { return count; } }
然后执行查询,必须指定命名空间过滤(默认命名空间为空字符串):
StatNsKind stat = ofy() .load() .type(StatNsKind.class) .filter("kind_name", entityName) .filter("namespace_name", "") // 若使用自定义命名空间,替换为对应字符串 .first() // 使用first()而非single(),无结果时返回null而非抛异常 .now(); if (stat != null) { Long entityCount = stat.getCount(); // 处理统计数值 }
方案2:直接查询原生Entity(无需创建实体类)
如果不想额外定义实体类,可以直接查询Datastore原生Entity对象,提取字段:
com.google.cloud.datastore.Entity statEntity = ofy() .load() .kind("__Stat_Ns_Kind__") .filter("kind_name", entityName) .filter("namespace_name", "") .first() .now(); if (statEntity != null) { Long count = statEntity.getLong("count"); // 处理统计数值 }
关键注意事项
- 不要尝试为
__Stat_Ns_Kind__创建自定义索引,系统实体的索引由Datastore自动维护,无法手动修改; - 必须过滤
namespace_name,否则会查询到所有命名空间下的统计记录,可能匹配不到目标结果; - 使用
first().now()替代single().now(),前者无结果时返回null,后者会抛出NotFoundException,更符合统计查询的场景。
内容的提问来源于stack exchange,提问作者Dimitar Genov
相关产品推荐
相关产品推荐

