App Engine Datastore: How to set multiple values on a property using golang?

妖精的绣舞 提交于 2019-12-08 10:45:27

问题


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:


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:


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


来源:https://stackoverflow.com/questions/29859001/app-engine-datastore-how-to-set-multiple-values-on-a-property-using-golang

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!