英文:
App Engine Datastore: How to set multiple values on a property using golang?
问题
我正在尝试使用Golang在Google的Datastore中保存单个属性的多个值。
我有一个int64的切片,我希望能够存储和检索它。从文档中我可以看到,通过实现PropertyLoadSaver{}接口可以支持这一点。但是我似乎无法得出正确的实现。
基本上,这是我想要实现的内容:
type Post struct {
Title string
UpVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
DownVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
}
c := appengine.NewContext(r)
p := &Post{
Title: "name",
UpVotes: []int64{23, 45, 67, 89, 10},
DownVotes: []int64{90, 87, 65, 43, 21, 123},
}
k := datastore.NewIncompleteKey(c, "Post", nil)
err := datastore.Put(c, k, p)
但是出现了"datastore: invalid entity type"错误。
英文:
I am trying to save multiple values for a single property in Google's Datastore using Golang.
I have a slice of int64 that I would like to be able to store and retrieve. From the documentation I can see that there is support for this by implementing the PropertyLoadSaver{} interface. But I cannot seem to come up with a correct implementation.
Essentially, this is what I'd like to accomplish:
type Post struct {
Title string
UpVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
DownVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
}
c := appengine.NewContext(r)
p := &Post{
Title: "name"
UpVotes: []int64{23, 45, 67, 89, 10}
DownVotes: []int64{90, 87, 65, 43, 21, 123}
}
k := datastore.NewIncompleteKey(c, "Post", nil)
err := datastore.Put(c, k, p)
But without the "datastore: invalid entity type" error.
答案1
得分: 3
多值属性在AppEngine中默认支持,您不需要做任何特殊的操作来使其工作。您不需要实现PropertyLoadSaver
接口,也不需要任何特殊的标签值。
如果结构体字段是切片类型,它将自动成为多值属性。以下代码可以工作:
type Post struct {
Title string
UpVotes []int64
DownVotes []int64
}
c := appengine.NewContext(r)
p := &Post{
Title: "name",
UpVotes: []int64{23, 45, 67, 89, 10},
DownVotes: []int64{90, 87, 65, 43, 21, 123},
}
k := datastore.NewIncompleteKey(c, "Post", nil)
key, err := datastore.Put(c, k, p)
c.Infof("Result: key: %v, err: %v", key, err)
当然,如果您希望,您可以为json和xml指定标签值:
type Post struct {
Title string
UpVotes []int64 `json:"-" xml:"-"`
DownVotes []int64 `json:"-" xml:"-"`
}
注意:
但请注意,如果属性被索引,多值属性不适合存储大量的值。这样做将需要许多索引(许多写操作)来存储和修改实体,而且可能会达到实体的索引限制(有关详细信息,请参阅索引限制和索引爆炸)。
因此,例如,您不能使用多值属性来存储Post
的数百个赞和踩。对于这个问题,您应该将投票作为单独/不同的实体存储,通过Post
的Key
或更好地只是它的IntID
来链接。
英文:
Multi-valued properties are supported by AppEngine by default, you don't need to do anything special to make it work. You don't need to implement the PropertyLoadSaver
interface, and you don't need any special tag value.
If a struct field is of a slice type, it will automatically be a multi-valued property. This code works:
type Post struct {
Title string
UpVotes []int64
DownVotes []int64
}
c := appengine.NewContext(r)
p := &Post{
Title: "name",
UpVotes: []int64{23, 45, 67, 89, 10},
DownVotes: []int64{90, 87, 65, 43, 21, 123},
}
k := datastore.NewIncompleteKey(c, "Post", nil)
key, err := datastore.Put(c, k, p)
c.Infof("Result: key: %v, err: %v", key, err)
Of course if you want you can specify tag value for json and xml:
type Post struct {
Title string
UpVotes []int64 `json:"-" xml:"-"`
DownVotes []int64 `json:"-" xml:"-"`
}
Notes:
But please note that multi-valued properties are not suitable to store a large number of values if the property is indexed. Doing so would require many indices (many writes) to store and modify the entity, and potentially you could hit the index limit for an entity (see Index limits and Exploding indexes for more details).
So for example you can't use a multi-valued property to store hundreds of up- and downvotes for a Post
. For that you should store votes as separate/different entities linking to the Post
e.g. by the Key
of the Post
or preferably just its IntID
.
答案2
得分: -1
你的程序在语法上有错误。
你确定你正在运行你认为的那段代码吗?例如,你的Post
没有必要用逗号分隔键/值对。
go fmt
应该会报告语法错误。
此外,datastore.Put()
返回多个值(键和错误),而代码只期望一个值。你应该在这一点上得到编译时错误。
首先纠正这些问题:当程序无法编译时,追逐虚假的语义错误没有意义。这是一个不会引发编译时错误的程序版本。
package hello
import (
"appengine"
"appengine/datastore"
"fmt"
"net/http"
)
type Post struct {
Title string
UpVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
DownVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
}
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
p := &Post{
Title: "name",
UpVotes: []int64{23, 45, 67, 89, 10},
DownVotes: []int64{90, 87, 65, 43, 21, 123},
}
k := datastore.NewIncompleteKey(c, "Post", nil)
key, err := datastore.Put(c, k, p)
fmt.Fprintln(w, "hello world")
fmt.Fprintln(w, key)
fmt.Fprintln(w, err)
}
英文:
Your program is syntactically malformed.
Are you sure you're running the code you think you're running? For example, your Post
doesn't have necessary commas that delimit the key/value pairs.
A go fmt
should be reporting syntax errors.
Also, datastore.Put()
returns multiple values (the key and the error), and the code is only expecting a single value. You should be getting compile-time errors at this point.
Correct those issues first: there no point chasing after phantom semantic errors when the program doesn't compile. Here is a version of your program that doesn't raise compile-time errors.
package hello
import (
"appengine"
"appengine/datastore"
"fmt"
"net/http"
)
type Post struct {
Title string
UpVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
DownVotes []int64 `json:"-" xml:"-" datastore:",multiple"`
}
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
p := &Post{
Title: "name",
UpVotes: []int64{23, 45, 67, 89, 10},
DownVotes: []int64{90, 87, 65, 43, 21, 123},
}
k := datastore.NewIncompleteKey(c, "Post", nil)
key, err := datastore.Put(c, k, p)
fmt.Fprintln(w, "hello world")
fmt.Fprintln(w, key)
fmt.Fprintln(w, err)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论