Appengine 数据存储区查询 returns 事务内的不同结果
Appengine Datastore query returns different result inside transaction
希望有人能帮助指出我代码中的问题。
我在事务外定义了一个查询,当它被执行时,它与数据库中的现有记录正确匹配。
但是,在事务内部执行查询的那一刻,它无法匹配数据库中的现有记录,尽管它们存在。
这是代码,输出如下:
// Query for URL to see if any already exist
existingRemoteURLQuery := datastore.NewQuery("RepoStats").
Filter("RepoURL =", statsToSave.RepoURL).
KeysOnly().Limit(1)
testKey, _ := existingRemoteURLQuery.GetAll(ctx, new(models.RepoStats))
if len(testKey) > 0 {
log.Infof(ctx, "TEST Update existing record vice new key")
} else {
log.Infof(ctx, "TEST No existing key found, use new key")
}
// Check if we already have a record with this remote URL
var key *datastore.Key
err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
// This function's argument ctx shadows the variable ctx from the surrounding function.
// last parameter is ignored because it's a keys-only query
existingKeys, err := existingRemoteURLQuery.GetAll(ctx, new(models.RepoStats))
if len(existingKeys) > 0 {
log.Infof(ctx, "Update existing record vice new key")
// use existing key
key = existingKeys[0]
} else {
log.Infof(ctx, "No existing key found, use new key")
key = datastore.NewIncompleteKey(ctx, "RepoStats", nil)
}
return err
}, nil)
如您在输出中所见,事务外的第一个查询与现有记录正确匹配。但在交易中,它不识别现有记录:
2018/08/28 11:50:47 INFO: TEST Update existing record vice new key
2018/08/28 11:50:47 INFO: No existing key found, use new key
提前感谢您的帮助
已更新
Dan 的评论导致打印出交易内查询的错误消息:
if err != nil {
log.Errorf(ctx, "Issue running in transaction: %v", err)
}
打印:
ERROR: Issue running in transaction: API error 1 (datastore_v3: BAD_REQUEST): Only ancestor queries are allowed inside transactions.
将评论转化为答案
事实证明这是尝试在事务内执行非祖先查询时的特定行为(FWIW,在 python 中尝试这样做实际上会引发异常)。
祖先查询是交易中唯一允许的查询。来自 What can be done in a transaction(不是很明确,恕我直言,因为查询可能 return 不符合交易限制的实体):
All Cloud Datastore operations in a transaction must operate on
entities in the same entity group if the transaction is a single-group
transaction, or on entities in a maximum of twenty-five entity groups
if the transaction is a cross-group transaction. This includes
querying for entities by ancestor, retrieving entities by key,
updating entities, and deleting entities. Notice that each root entity
belongs to a separate entity group, so a single transaction cannot
create or operate on more than one root entity unless it is a
cross-group transaction.
希望有人能帮助指出我代码中的问题。
我在事务外定义了一个查询,当它被执行时,它与数据库中的现有记录正确匹配。
但是,在事务内部执行查询的那一刻,它无法匹配数据库中的现有记录,尽管它们存在。
这是代码,输出如下:
// Query for URL to see if any already exist
existingRemoteURLQuery := datastore.NewQuery("RepoStats").
Filter("RepoURL =", statsToSave.RepoURL).
KeysOnly().Limit(1)
testKey, _ := existingRemoteURLQuery.GetAll(ctx, new(models.RepoStats))
if len(testKey) > 0 {
log.Infof(ctx, "TEST Update existing record vice new key")
} else {
log.Infof(ctx, "TEST No existing key found, use new key")
}
// Check if we already have a record with this remote URL
var key *datastore.Key
err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
// This function's argument ctx shadows the variable ctx from the surrounding function.
// last parameter is ignored because it's a keys-only query
existingKeys, err := existingRemoteURLQuery.GetAll(ctx, new(models.RepoStats))
if len(existingKeys) > 0 {
log.Infof(ctx, "Update existing record vice new key")
// use existing key
key = existingKeys[0]
} else {
log.Infof(ctx, "No existing key found, use new key")
key = datastore.NewIncompleteKey(ctx, "RepoStats", nil)
}
return err
}, nil)
如您在输出中所见,事务外的第一个查询与现有记录正确匹配。但在交易中,它不识别现有记录:
2018/08/28 11:50:47 INFO: TEST Update existing record vice new key
2018/08/28 11:50:47 INFO: No existing key found, use new key
提前感谢您的帮助
已更新
Dan 的评论导致打印出交易内查询的错误消息:
if err != nil {
log.Errorf(ctx, "Issue running in transaction: %v", err)
}
打印:
ERROR: Issue running in transaction: API error 1 (datastore_v3: BAD_REQUEST): Only ancestor queries are allowed inside transactions.
将评论转化为答案
事实证明这是尝试在事务内执行非祖先查询时的特定行为(FWIW,在 python 中尝试这样做实际上会引发异常)。
祖先查询是交易中唯一允许的查询。来自 What can be done in a transaction(不是很明确,恕我直言,因为查询可能 return 不符合交易限制的实体):
All Cloud Datastore operations in a transaction must operate on entities in the same entity group if the transaction is a single-group transaction, or on entities in a maximum of twenty-five entity groups if the transaction is a cross-group transaction. This includes querying for entities by ancestor, retrieving entities by key, updating entities, and deleting entities. Notice that each root entity belongs to a separate entity group, so a single transaction cannot create or operate on more than one root entity unless it is a cross-group transaction.