为什么过滤器在未指定祖先时不起作用?不管是祖先,它不应该在实体类型上工作吗?
我的使用案例:我已使用父密钥设置了多个实体。密钥对应于另一个实体(主实体),以便我可以通过祖先(主实体密钥)获取子代。
然而,问题似乎是我不能再查询实体属性,除非我指定了祖先。这是应该的方式吗?下面是一些伪代码。如果问题不明确,我可以提供工作代码。
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)
答案 0 :(得分:1)
简答:
使用父级保存的实体可以查询非祖先查询(您没有使用Query.Ancestor()
方法指定祖先)。显然,必须将过滤后的属性编入索引。
要落实到位:
在您的示例中,与您的命名key1
相反的是父密钥,而kparent
是您保存实体的密钥。
使用Query.Ancestor()
方法创建祖先查询时,ancestor filter将结果限制为指定实体及其后代:因此您指定了父键,结果将是具有这个键(0或1实体)和那个是父键的那些!
在您的示例中,您可以找到结果,因为实体的键正是您指定的键。通常,祖先查询的使用方式是指定父键(而不是实体的键本身),在您的示例中为key1
。
需要注意的重要事项:祖先查询非常一致。这意味着如果您使用父级保存实体并在此之后执行祖先查询(祖先过滤器是同一个父级)当然),将立即在查询结果中查看已保存的实体。
非祖先查询仅最终一致。这意味着如果您保存实体并在此之后立即执行非祖先查询,则查询将不包括新保存的实体的可能性非常高,这很可能是您的情况。
属性的索引仅取决于属性的值,并且独立于实体的密钥,因此,如果密钥具有父级,则无关紧要。一旦为新实体创建了属性的索引条目,由该属性过滤的查询将包括该实体。这可能需要短至几毫秒或长期"几秒钟(不太可能)。
请参阅此相关答案:How to filter a GAE query?,其中还解释了祖先密钥和查询。
答案 1 :(得分:0)
您正在比较两个不同的查询 - 并且祖先键不是唯一的区别。例如,如果未对filter属性建立索引,则第二个查询将不返回任何结果。