英文:
Putting many PropertyList's into Google App Engine datastore (in Go) and loading them again with Query.GetAll
问题
我正在将实体(作为datastore.PropertyList
)存储到数据存储中,就像这样:
// 保存一个
var plist datastore.PropertyList = make(datastore.PropertyList, 3)
plist = append(plist, datastore.Property { "name", "Mat", false, false })
plist = append(plist, datastore.Property { "age", "29", false, false })
plist = append(plist, datastore.Property { "location", "London", false, false })
key := datastore.NewIncompleteKey(context, "Record", nil)
datastore.Put(context, key, &plist)
// 保存另一个
var plist datastore.PropertyList = make(datastore.PropertyList, 3)
plist = append(plist, datastore.Property { "name", "Laurie", false, false })
plist = append(plist, datastore.Property { "age", "27", false, false })
plist = append(plist, datastore.Property { "location", "London", false, false })
key := datastore.NewIncompleteKey(context, "Record", nil)
datastore.Put(context, key, &plist)
这一切都正常工作(尽管上面的代码现在更像是伪代码)。我能够单独加载它们,并且datastore.PropertyList
中的每个字段都作为自己的datastore.Property
出现。
然而,当我尝试使用Query
检索它们时,出现错误:
query := datastore.NewQuery("Record")
plists := make(datastore.PropertyList, 0, 10)
keys, err := query.GetAll(context, &plists)
我得到以下错误:
datastore: 无法将字段"age"加载到"datastore.Property"中:没有这样的结构字段
它似乎不会对Name
抱怨,因为那恰好是datastore.Property
的有效属性,那么我该如何使其按预期加载项目,使plists
中的每个项目都是datastore.PropertyList
而不是datastore.Property
?
英文:
I am putting entities (as a datastore.PropertyList
) into the datastore like this:
// save one
var plist datastore.PropertyList = make(datastore.PropertyList, 3)
plist = append(plist, datastore.Property { "name", "Mat", false, false })
plist = append(plist, datastore.Property { "age", "29", false, false })
plist = append(plist, datastore.Property { "location", "London", false, false })
key := datastore.NewIncompleteKey(context, "Record", nil)
datastore.Put(context, key, &plist)
// save another one
var plist datastore.PropertyList = make(datastore.PropertyList, 3)
plist = append(plist, datastore.Property { "name", "Laurie", false, false })
plist = append(plist, datastore.Property { "age", "27", false, false })
plist = append(plist, datastore.Property { "location", "London", false, false })
key := datastore.NewIncompleteKey(context, "Record", nil)
datastore.Put(context, key, &plist)
That all works fine (although the code above is more like pseudo code for now). I am able to load them individually, and the datastore.PropertyList
comes out with each field as its own datastore.Property
.
However, when I try to retrieve many of them using a Query
, it fails:
query := datastore.NewQuery("Record")
plists := make(datastore.PropertyList, 0, 10)
keys, err := query.GetAll(context, &plists)
I get the following error:
datastore: cannot load field "age" into a "datastore.Property": no such struct field
It seems that it doesn't complain about Name
because that happens to be a valid property of datastore.Property
, so how do I get it to load the items as intended, with each item in plists
being a datastore.PropertyList
instead of datastore.Property
?
答案1
得分: 3
我将实现更改为使用PropertyLoadSaver
接口 - 您可以在我们的新活动记录样式的数据存储包装器中看到它正常工作:http://github.com/matryer/gae-records(请参阅record.go
类型的Load
和Save
方法)
英文:
I changed the implementation to use the PropertyLoadSaver
interface - you can see it working nicely in our new Active Record style wrapper for datastore: http://github.com/matryer/gae-records (see the record.go
type's Load
and Save
methods)
答案2
得分: 2
> GetAll在给定的上下文中运行查询,并返回与该查询匹配的所有键,同时将值附加到dst。dst必须是一个指向结构体、结构体指针或映射的切片的指针。如果q是一个“仅键”查询,GetAll会忽略dst,只返回键。
根据以下帖子,go datastore模块尚不支持PropertyList。
请使用指向datastore.Map切片的指针。
还要注意,您需要调用make([]T, n)
来创建一个T
的切片,而不是make(T, n)
。
英文:
> GetAll runs the query in the given context and returns all keys that match that query, as well as appending the values to dst. The dst must be a pointer to a slice of structs, struct pointers, or Maps. If q is a “keys-only” query, GetAll ignores dst and only returns the keys.
And according to the following post the go datastore module doesn't support PropertyList yet.
Use a pointer to a slice of datastore.Map instead.
Also note that you need to do call make([]T, n)
in order to make a slice of T
, not make(T, n)
答案3
得分: 2
尝试使用大写字母编写字段名称,例如,不要使用age
,而是使用Age
。这告诉Go语言该字段是可导出的(类似于公共变量的概念,尽管它比这更进一步)。
根据Go数据存储文档(查看函数部分的Get方法),当调用Get
或GetAll
方法时,如果要将字段加载到与存储字段类型不同的类型中,或者目标结构体中缺少或未导出字段,则会返回ErrFieldMismatch
错误。只有当dst是结构体指针时才会返回ErrFieldMismatch。我猜测,由于您将其存储为具有未导出名称的PropertyList
,并且由于数据存储在模型方面具有灵活性,它将将原始值视为未导出,因为它们是小写字母。
我目前遇到了相同的错误,但我成功追踪到它是由于一些空字段造成的。
如果这解决了您的问题,请告诉我。
英文:
Try writing your field names with a capital letter, for example, instead of age
, write Age
. This tells Go that your field is exported (it's similar to the concept of public variables, though it goes a bit further than that).
According to the Go datastore documentation (look at the Get method in the Functions section), a Get
or GetAll
method call, will return an ErrFieldMismatch
"when a field is to be loaded into a different type than the one it was stored from, or when a field is missing or unexported in the destination struct. ErrFieldMismatch is only returned if dst is a struct pointer.". My best guess is that since you stored it as a PropertyList
with unexported names, and since the datastore is flexible in its models, it will take the original values as unexported, due to their lowercase letters.
I am currently having the same error, but I managed to track it down to being due to some empty fields.
If this solves your problem, please let me know.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论