类型与 [] 字节属性上的投影不匹配



我有一个结构如下

type MyEntity struct {
PF []byte `json:"-" datastore:"_pf"`
}

在没有投影的情况下进行查询工作正常。但是,当我使用"_pf"字段上的投影进行查询时,出现"类型不匹配:字符串与 []uint8"错误。我实现了 PropertyLoadSaver 并检查了道具。"_pf"属性的值,发现某些行返回 []byte 类型,某些返回字符串。那么,为什么投影查询失败并出现此错误,而非投影查询却很好?目前,我正在通过实现 PropertyLoadSaver 接口并显式检查类型并将字符串类型转换为 []byte 类型来解决此问题。

这是完整的测试用例。这在云数据存储模拟器上重现。对下面的数据存储项目变量使用适当的值。其余的都应该直接工作。您可以通过插入两个实体或实体类型之一来查看行为。显示的错误是

panic: datastore: cannot load field "_pf" into a "tests.MyEntity": type mismatch: string versus []uint8 [recovered]
panic: datastore: cannot load field "_pf" into a "tests.MyEntity": type mismatch: string versus []uint8

以下是代码。

type MyEntity struct {
PF []byte `json:"-" datastore:"_pf"`
}
func TestPackedField(t *testing.T) {
e1 := &MyEntity{PF: []byte{83, 0, 0, 0, 93, 150, 154, 206, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 3}} // returns []byte on projection
e2 := &MyEntity{PF: []byte{83, 0, 0, 0, 93, 120, 79, 87, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 3}}   // returns string on projection
ctx := context.Background()
conn, err := datastore.NewClient(ctx, datastoreProject)
if err != nil {
panic(err)
}
bkey := datastore.NameKey("Bytes", "bytearray", nil)
if true {
conn.Put(ctx, bkey, e1)
}
skey := datastore.NameKey("Bytes", "string", nil)
if true {
conn.Put(ctx, skey, e2)
}
q1 := datastore.NewQuery("Bytes").Order("-_pf").Limit(2)
var elfull []*MyEntity
if _, err := conn.GetAll(ctx, q1, &elfull); err != nil {
panic(err)
}
q2 := datastore.NewQuery("Bytes").Project("_pf").Order("-_pf").Limit(2)
var elprojected []*MyEntity
if _, err := conn.GetAll(ctx, q2, &elprojected); err != nil {
conn.Delete(ctx, bkey)
conn.Delete(ctx, skey)
panic(err)
}
}

为了理解为什么这在普通查询上工作正常,而不是在投影查询上,您可能首先要了解这两者之间的实际区别是什么。正如这篇文章中提到的:

虽然针对云数据存储的"常规"(我的意思是 SELECT * ...(查询通常使用仅包含查询实体属性的排序子集的索引,以及指向完整实体的指针,但投影查询针对包含查询请求的所有字段的索引运行。因此,似乎显着的延迟增益来自于一旦通过索引识别出与查询匹配的实体集,就无需获取查询的实体。

因此,基本上,当您执行投影查询时,不会提取查询的实体。

当我阅读此官方文档时,我发现了一些与您的问题相关的非常有趣的短语:

切片类型的字段对应于数据存储数组属性,但 []byte 除外,它对应于数据存储 blob。如果将非数组值加载到切片字段中,则结果将是具有一个包含该值的元素的切片。

关键字段 如果结构包含 *数据存储。标有名称">key"的键字段,其值将在 Put 上被忽略。将实体读回 Go 结构时,将使用 *数据存储填充该字段。用于查询实体的键值。

我从这里了解到,也许在您的情况下,字段填充了该查询的键值(字符串(。

我发现的另一个有趣的事情是,根据属性和值类型文档,类型[]byte没有索引。正如这里所说,无法投影未编制索引的属性。因此,投影查询根本不应该适用于此特定用例。

最新更新