查询Cloud Datastore中的嵌入式实体

时间:2016-12-13 20:23:41

标签: java google-cloud-datastore google-cloud-platform eventual-consistency

关于在数据存储区中使用嵌入式实体,我有几个问题。

考虑以下简单的测试用例:

Entity entity = new Entity("Person");

entity.setProperty("name", "Alice");
EmbeddedEntity address = new EmbeddedEntity();
address.setProperty("streetAddress", "100 Main Street");
address.setProperty("addressLocality", "Springfield");
address.setProperty("addressRegion", "VA");

entity.setProperty("address", address);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(entity);

Query query = new Query("Person");
FilterPredicate regionFilter = 
    new FilterPredicate("address.addressRegion", FilterOperator.EQUAL, "VA");
query.setFilter(regionFilter);

List<Entity> results = datastore.prepare(query)
    .asList(FetchOptions.Builder.withDefaults());

assertEquals(1, results.size());

此测试失败;结果集为空。

以下是我的问题:

  1. 我正确使用FilterPredicate吗?该文档未解释如何引用EmbeddedEntity的属性。我猜这个约定是使用点分隔的路径。但也许这不正确。
  2. 我的测试用例是否需要为嵌入式地址实体中的子属性声明索引?如果是这样,怎么样?
  3. Datastore documentation包含以下声明:

    &#34;当嵌入式实体包含在索引中时,您可以查询子属性。&#34;

    我遵循关于Java Local Unit Testing的文章中的说明,但文章中没有解释如何在JUnit测试中定义索引的内容。

1 个答案:

答案 0 :(得分:1)

由于最终的一致性,这项测试很不稳定。

由于您没有进行祖先查询,因此查询最终使用一致的索引(SELECT * FROM Person WHERE address.addressRegion = "VA")。插入和查询不能保证匹配相同的副本,address.addressRegion也不能保证更新。

默认情况下,嵌入式实体应编入索引,以免出现问题。

最终的一致性通常以毫秒为单位进行解决,但由于您正在立即编写和查询,因此您更有机会点击它。

您可以采用两种策略来降低测试的薄脆度。

1。睡

在put和查询之间添加1或2秒的睡眠将减少测试的瑕疵,但不能消除它 - 可能是合理的第一步。我一眼就看出它没有运行你的代码。

2。强制应用索引写入

Cloud Datastore同步将实体写入多数副本,但是在此步骤之后异步应用索引 - 这会导致某些查询的最终一致性。

您可以通过执行相关实体的读取来强制应用索引。读取实体时,将检查实体组的写日志,以查看是否存在要应用的未完成写入 - 如果在读取之前强制应用它们。您可以在单元测试中使用此机制来减少最终的一致性问题。

杂项

此外,要验证实体是否按预期编写,您可以跳转到云控制台并从上面执行GQL语句。