【问题标题】:AppEngine Datastore query with filter never returns results (Go)带有过滤器的 AppEngine 数据存储区查询从不返回结果 (Go)
【发布时间】:2016-08-08 12:38:58
【问题描述】:

如果我不使用过滤器,我会得到结果。如果我使用过滤器(这条记录肯定存在),我不会得到任何结果。可能是缺少为该属性定义的索引,但据我了解,应该在开发服务器中自动创建简单的索引(并创建一个 index.yaml 文件并用它填充)。这不会发生。

query = datastore.NewQuery("UserAccount").Filter("email =", "test@example.com")

ua := UserAccount{}
t := query.Run(ctx)
for ; ; {
    if _, err = t.Next(&ua); err == nil {
        log.Debugf(ctx, "Current: %s", ua)
    } else if err == datastore.Done {
        break
    } else {
        panic(err)
    }
}

当开发服务器终止时,它声明它正在“保存搜索索引”:

INFO     2016-08-08 05:09:52,894 api_server.py:651] Saving search indexes

但是,由于没有出现“index.yaml”文件,我假设不需要创建索引,这意味着我的查询一定没有达到预期的效果?

我错过了什么?

编辑:

请注意,该记录是之前创建的,此后应用程序停止并启动了很多次。我真诚地怀疑这是最终一致性的事情。

编辑 2:

出于测试目的,我使用以下代码创建了以下模型。它们都表现出与我的原始模型和代码相同的行为。

定义:

type TestEntity struct {
    Email string
}

代码:

log.Debugf(ctx, "Putting.")

email := "anothertest@a.b"

te := &TestEntity{
        Email: email,
}

k := datastore.NewKey(ctx, "TestEntity", "123", 0, nil)
_, err = datastore.Put(ctx, k, te)
if err != nil {
    panic(err)
}

log.Debugf(ctx, "Waiting.")
time.Sleep(1 * time.Second)

query := datastore.NewQuery("TestEntity")

var results []TestEntity
_, err = query.GetAll(ctx, &results)
log.Debugf(ctx, "GetAll: %s", results)

log.Debugf(ctx, "Running query.")

query = datastore.NewQuery("TestEntity").Filter("email =", email)

te = &TestEntity{}
t := query.Run(ctx)
for ; ; {
    if _, err = t.Next(te); err == nil {
        log.Debugf(ctx, "Found: [%s]", te.Email)
    } else if err == datastore.Done {
        log.Debugf(ctx, "Done.")
        break
    } else {
        panic(err)
    }
}

结果:

2016/08/09 02:11:36 DEBUG: Putting.
2016/08/09 02:11:36 DEBUG: Waiting.
2016/08/09 02:11:37 DEBUG: GetAll: [{anothertest@a.b}]
2016/08/09 02:11:37 DEBUG: Running query.
2016/08/09 02:11:37 DEBUG: Done.

查看器的屏幕截图:

【问题讨论】:

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


【解决方案1】:

数据存储区中的属性名称是"Email",大写E,而不是"email"

区分大小写,必须用大写E查询:

query = datastore.NewQuery("UserAccount").Filter("Email =", "test@example.com")

如果您希望使用小的e 保存/检索它,您可以使用tags 进行映射,例如:

type UserAccount struct {
    Email string `datastore:"email"`
    // other fields...
}

【讨论】:

  • 感谢您注意到一些我太愚蠢而无法注意到自己的事情。那是一条有趣的三十条消息。至少我们建立了看到“未索引”事物的可能性。此外,我得到了结果,但我仍然没有在管理员或“index.yaml”文件中看到任何索引。正如 DanCornilescu 之前提到的,永远不能表示简单的索引(这似乎会使计算写入的成本估算变得更加困难)。最后,我注意到当我在 Go(“goapp serve”)下运行我的 AppEngine 版本时,我得到一个脚注,上面写着它包装了 Python 开发服务器。
  • @DustinOprea 只有复合索引需要添加到index.yaml。单一属性指数没有。单个属性索引存在于 每个实体 的基础上:一个实体可能具有索引的 Email 属性,另一个可能具有未索引的 Email 属性,第三个甚至可能没有此类属性。甚至 4th 也可能有一个,但类型不同...... Datastore 不是关系数据库,它是无模式的。
  • @DustinOprea 是的,Go SDK 使用 python 开发服务器,这已经不是什么秘密了。
  • 我预计不会看到 index.yaml 文件(我说的用户已经提到过它),但为了后代而声明它。但是,我确实希望看到简单索引填充到“数据存储索引”面板中。我还想暗示,如果您调用 Java 风格的命令行帮助,您可能会得到相同的指示(它使用 Python 服务器)。
  • @DustinOprea 单一属性索引不需要明确定义,它们不会出现在索引页面上。只有复合指数。 Go 部分没有偏差。属性索引“只是”存在,如果没有条目,它们只会“消失”。
【解决方案2】:

为了能够通过属性必须在创建实体时(在模型定义中)启用索引的属性在查询/过滤的结果中找到实体,并且必须为其完成数据存储的后台索引任务。

如果您在创建实体之后为该属性启用索引,您需要重新编写该属性以便为其触发索引任务,请参阅:https://stackoverflow.com/a/34583510/4495081

“正在保存搜索索引”消息是在操作发生之前打印的通用消息,并不意味着操作的结果将是非空的。

您不必担心您的index.yaml 文件是空的。并非所有索引都需要存在于index.yaml 文件中,只有更复杂/复合的索引才需要。您的过滤器可以使用内置索引进行匹配(在满足上述索引要求后)。来自Indexes

有两种类型的索引:

  • 内置索引

    默认情况下,Cloud Datastore 会自动为每种实体类型的每个属性预定义一个索引。这些单一属性索引是 适用于简单类型的查询。

  • 复合索引

    复合索引为每个索引实体索引多个属性值。复合索引支持复杂查询,定义在 一个索引配置文件(index.yaml)。

【讨论】:

  • 目前尚不清楚如何标记属性以进行索引,甚至是否受支持。该文档仅在 preventing 索引的上下文中提及标记:(cloud.google.com/appengine/docs/go/datastore/indexes) "Age int datastore:",noindex""
  • 确实,在这方面,go 似乎与 python 不同。答案仍然适用 - 您可能在创建实体时禁用了索引 :)
  • @DustinOprea:您可以在 Cloud Console 数据存储区查看器中查看属性是否已编入索引。找到一个实体并单击编辑图标 - 它会显示所有属性。
  • @AndreiVolgin 我从未对该列进行过搜索,但我的理解是隐式创建了简单的索引。然而,情况似乎并非如此。我尝试创建一个带有一些语法错误的 index.yaml 来测试它是否会被加载(如果启动时出现错误,那么显然有一个 attempt 来加载它),我可以有效地在那里添加一个明确的。但是,开发环境似乎在启动时完全忽略了它。有什么想法吗?
  • @DustinOprea 我怀疑开发服务器仅在遇到需要复合索引的查询时才读取index.yaml 文件 - 检查是否需要将索引添加到文件中。尝试在您的代码中添加一个复合查询只是为了测试这个理论 - 开发服务器 应该 因为不正确的现有 index.yaml 文件而失败,或者如果理论正确,则愉快地从头开始重新生成它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
相关资源
最近更新 更多