user6043285
user6043285

Reputation:

How to get ID from the datastore to update the entity?

I am building a REST API to do CRUD Operations,

I have a Go struct:

type VisitEntiry struct {
    FirstName string `json:"firstname"`
    LastName string `json:"lastname"`
    UserName string `json:"username"`
    PassWord string `json:"password"`
    Email string `json:"email"`
}

I am able to save and retrieve VisitEntiries in datastore. So I need to edit visit entity, I want to get the ID that datastore assigns a VisitEntiry to use. I verified that IDs are assigned using Google's datastore dashboard, but how do I get the ID off of a retrieved VisitEntiry?

Cloud you Please help me to write the code to EDIT the Entities.

import (
    "encoding/json"
    "log"
    "net/http"
    "golang.org/x/net/context"
    "google.golang.org/appengine"
    "google.golang.org/appengine/datastore"
)

const KINDNAME = "Vist"

const NAMESPACENAME = "-Test-"

type VisitEntiry struct {
    FirstName string `json:"firstname"`
    LastName string `json:"lastname"`
    UserName string `json:"username"`
    PassWord string `json:"password"`
    Email string `json:"email"`
}
var visit *VisitEntiry
//SuccessResponse store response
type SuccessResponse struct {
    //  visit VisitEntiry `json:"entity"`
    ID int64 `json:"Id"`
    Message string `json:"message"`
}
func init() {
    http.HandleFunc("/api/getallvisits", restHandler)
    http.HandleFunc("/api/postavisit", restHandler)
}
func restHandler(w http.ResponseWriter, r *http.Request) {
    var v VisitEntiry
    _ = json.NewDecoder(r.Body).Decode(&v)
    json.NewEncoder(w).Encode(v)
    visit = &VisitEntiry{
        FirstName: v.FirstName,
        LastName: v.LastName,
        UserName: v.UserName,
        PassWord: v.PassWord,
        Email: v.Email,
    }
    switch r.Method {
    case "GET":
        getallvisitshandler(w, r)
        return
    case "POST":
        putavisthandler(w, r)
        return
    case "DELETE":
        //  handleDelete(ed, w, r)
        return
    default:
        //respondErr(w, r, http.StatusNotFound, "is not supported HTTP methods")
    }
}
func respond(w http.ResponseWriter, r *http.Request, status int, data interface{}) {
    w.WriteHeader(status)
    if data != nil {
        json.NewEncoder(w).Encode(data)
    }
}
func getallvisitshandler(w http.ResponseWriter, r *http.Request) {

    var visitslist []VisitEntiry
    var ctx context.Context
    ctx = appengine.NewContext(r)
    ctx, err := appengine.Namespace(ctx, NAMESPACENAME)
    if err != nil {
        return
    }
    q := datastore.NewQuery(KINDNAME)
    _, err = q.GetAll(ctx, &visitslist)
    json.NewEncoder(w).Encode(visitslist)
    //log.Printf("%#v Getting values From Datastore - visits ", visitskeys)
}
func putavisthandler(w http.ResponseWriter, r *http.Request) {
    var ctx context.Context
    keys := make([]*datastore.Key, 1)
    ctx = appengine.NewContext(r)
    ctx, err := appengine.Namespace(ctx, NAMESPACENAME)
    if err != nil {
        return
    }
    keys[0] = datastore.NewIncompleteKey(ctx, KINDNAME, nil)
    visitentity, err := datastore.Put(ctx, keys[0], visit)
    ID := visitentity.IntID()
    value := visitentity.Encode()
    //value : = visitentity.Encode()
    log.Printf("%#v Getting values From Datastore - visits ", value)
    respond(w, r, http.StatusOK, SuccessResponse{ID, "Visit Entity Inserted Successfully! "})
}

Upvotes: 1

Views: 1501

Answers (1)

icza
icza

Reputation: 417402

Getting key of entity on save

When you put a new entity into the Datastore e.g. with the datastore.Put() function, you'll get the assigned key in return:

func Put(c context.Context, key *Key, src interface{}) (*Key, error)

Updating an existing entity

To update an existing entity in the datastore, you first need to get it from the datastore.

This may happen by already knowing its key, and getting it using datastore.Get(). In this case you obviously already have the key.

You may also get the entities to update by running a query. In this case in the end you would get the entities by executing the Query.GetAll() method. Query.GetAll() returns you the keys of the entities that it returns:

func (q *Query) GetAll(c context.Context, dst interface{}) ([]*Key, error)

So for example if the query returns 10 entities (that will be stored in dst), it will also return the 10 corresponding keys as a slice for the returned entities. So you also have your keys.

Another option is to use a query iterator, obtained by Query.Run(). In which case you would get the actual entities by calling Iterator.Next() which again returns the key:

func (t *Iterator) Next(dst interface{}) (*Key, error)

Transferring entity keys

For a client to update an entity, it must have some kind information which uniquely identifies the entity, conveniently its key. So when the client requests the entity, the server should also send its key along. And when the client wants to update the entity, along with the updated data it has to send the key along. So the server will be able to update the proper entity denoted by the key.

To send a key to a client, you may use the Key.Encode() method which encodes the key to a web-safe string.

The client should send back this same key string.

And the server may use the datastore.DecodeKey() function to turn the key string back to a *datastore.Key value.

Note: if you're using numeric IDs and you know the kind, you may opt to only transfer the numeric ID. You can acquire the numeric ID using the Key.IntID() method. And you may use datastore.NewKey() to construct a key from a numeric ID at server side like this:

numericID = int64(0) // Get this from the request
key := datastore.NewKey(ctx, KINDNAME, "", numericID, nil)

Check out this answer about keys: Can I use AllocateIDs as "string" ? datastore

Upvotes: 3

Related Questions