为什么查询在未提供祖先时不返回结果?

时间:2015-04-09 03:35:58

标签: google-app-engine go google-cloud-datastore

为什么过滤器在未指定祖先时不起作用?不管是祖先,它不应该在实体类型上工作吗?

我的使用案例:我已使用父密钥设置了多个实体。密钥对应于另一个实体(主实体),以便我可以通过祖先(主实体密钥)获取子代。

然而,问题似乎是我不能再查询实体属性,除非我指定了祖先。这是应该的方式吗?下面是一些伪代码。如果问题不明确,我可以提供工作代码。

type MyStruct{
  Unique int
}

 key1 := datastore.NewKey(c, "table1", "verylongstring", 0, nil)
 kparent :=  datastore.NewKey(c, "table1", "anotherlongstring", 0, key1)
 x := MyStruct{Unique:23}
 if _, err := datastore.Put(c, kparent, &x); err != nil {
        panic(err)
 }

// This works
 _, err := datastore.NewQuery("table1").Ascentor(kparent).Filter("Unique =", v.Unique).GetAll(cx, dst)

// Query with filter without ancestor doesn't work. Returns no results error.
 _, err := datastore.NewQuery("table1").Filter("Unique =", v.Unique).GetAll(cx, dst)

2 个答案:

答案 0 :(得分:1)

简答:

使用父级保存的实体可以查询非祖先查询(您没有使用Query.Ancestor()方法指定祖先)。显然,必须将过滤后的属性编入索引。

要落实到位:

在您的示例中,与您的命名key1相反的是父密钥,而kparent是您保存实体的密钥。

使用Query.Ancestor()方法创建祖先查询时,ancestor filter将结果限制为指定实体及其后代:因此您指定了父键,结果将是具有这个键(0或1实体)和那个是父键的那些!

在您的示例中,您可以找到结果,因为实体的键正是您指定的键。通常,祖先查询的使用方式是指定父键(而不是实体的键本身),在您的示例中为key1

需要注意的重要事项:祖先查询非常一致。这意味着如果您使用父级保存实体并在此之后执行祖先查询(祖先过滤器是同一个父级)当然),立即在查询结果中查看已保存的实体。

非祖先查询仅最终一致。这意味着如果您保存实体并在此之后立即执行非祖先查询,则查询将不包括新保存的实体的可能性非常高,这很可能是您的情况。

属性的索引仅取决于属性的值,并且独立于实体的密钥,因此,如果密钥具有父级,则无关紧要。一旦为新实体创建了属性的索引条目,由该属性过滤的查询将包括该实体。这可能需要短至几毫秒或长期"几秒钟(不太可能)。

请参阅此相关答案:How to filter a GAE query?,其中还解释了祖先密钥和查询。

答案 1 :(得分:0)

您正在比较两个不同的查询 - 并且祖先键不是唯一的区别。例如,如果未对filter属性建立索引,则第二个查询将不返回任何结果。