【问题标题】:Appengine Datastore query returns different result inside transactionAppengine Datastore 查询在事务中返回不同的结果
【发布时间】:2018-08-28 11:59:30
【问题描述】:

希望有人能帮助指出我代码中的问题。

我在事务外部定义了一个查询,当它执行时,它正确匹配数据库中的现有记录。

但是,在事务中执行查询时,它无法匹配数据库中的现有记录,尽管它们存在。

这是代码,输出如下:

// 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)
    }

哪些打印:

错误:事务中运行的问题:API 错误 1(datastore_v3:BAD_REQUEST):事务中只允许祖先查询。

【问题讨论】:

  • FWIW,在 python 中,甚至不允许在事务内部进行非祖先查询(引发异常),也许您看到的是这种情况下特定于 go 的行为。见What can be done in a transaction
  • @DanCornilescu 原来是答案。我没有检查返回的错误值。添加了一条日志语句以将其打印出来,并给出以下响应:existingKeys, err := existingRemoteURLQuery.GetAll(ctx, new(models.RepoStats)) if err != nil { log.Errorf(ctx, "Issue running in transaction: %v", err) }

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


【解决方案1】:

将评论转化为答案

事实证明,当尝试在事务中执行非祖先查询时,这是特定于 go 的行为(FWIW,在 python 中尝试这样做实际上会引发异常)。

祖先查询是事务中唯一允许的查询。来自What can be done in a transaction(虽然不是很明确,恕我直言,因为查询可能会返回不符合事务限制的实体):

事务中的所有 Cloud Datastore 操作都必须在 如果事务是单个组,则属于同一实体组中的实体 交易,或最多 25 个实体组中的实体 如果事务是跨组事务。这包括 按祖先查询实体,按键检索实体, 更新实体和删除实体。请注意,每个根实体 属于单独的实体组,因此单个事务不能 创建或操作多个根实体,除非它是 跨组交易。

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    相关资源
    最近更新 更多