Simon Guldstrand
Simon Guldstrand

Reputation: 488

golang datastore get object

I need some guidance whether I am doing this correct. Im trying to get a single object of a car. This is how I create a car:

 car := &types.Car{
            Model:        req.Model,
            Regnr:        req.Regnr,
            Year:         req.Year,
            Type:         req.Type,
            CreationTime: time.Now(),
            Sold:         false,
        }
        //key := datastore.NewKey(context, "Car", "", 0, nil)

        _, err := datastore.Put(context, datastore.NewIncompleteKey(context, "Car", nil), car)

This is the way im trying to get the car again.

vars := mux.Vars(r)
        regnr := vars["regnr"]
        car := types.Car{}
        carKey := datastore.NewKey(context, "Car", regnr, 0, nil)
        err := datastore.Get(context, carKey, &car)
        if err != nil {
            log.Println("error getting car", err)
            w.WriteHeader(http.StatusInternalServerError)
            return
        }

But I get the error: "error getting car datastore: no such entity"

I know I can do a GetAll and limit to one. But if im deleting an object, I need the entity. I guess. So I want to do it right.

Thanks!

Upvotes: 2

Views: 780

Answers (2)

icza
icza

Reputation: 417452

You can't find the inserted entity, because it was saved with a different key than the one you try to get it by.

This line:

_, err := datastore.Put(context, datastore.NewIncompleteKey(context, "Car", nil), car)

Saves a Car entity with a newly created, incomplete key. If you try to save an entity with an incomplete key, the datastore will assign a (randomly distributed) unique numeric ID to it. A numeric ID, not a string name.

And then you try to get it with a key having a string name:

carKey := datastore.NewKey(context, "Car", regnr, 0, nil)

They will never match! The identifier part of an entity's key can either be

  • a key name string
  • or an integer numeric ID

But not both. So when you save an entity, its key either has a string id called name OR (exclusive OR) an int64 id called intID.

Please do read my answer about entity identifiers: Can I use AllocateIDs as “string” ?

Your options are:

I. regnr as string name

Either use regnr as a string name if you do have guarantee it's unique, and it is always present (no entity to be saved without regnr):

carKey := datastore.NewKey(context, "Car", req.Regnr, 0, nil)

This is not an incomplete key if req.Regnr is not an empty string, and thus it will be used as the string name of the entity's key. Which means later you can get this entity by:

carKey := datastore.NewKey(context, "Car", regnr, 0, nil)
err := datastore.Get(context, carKey, &car)

II. regnr as "normal" property

Or define regnr as a "normal" property and save entities with an incomplete key, leaving the unique numeric ID assignment to the system. This won't limit you in finding entities by regnr as you can filter entities by it if it's an indexed property. In this alternative regnr is not part of the entity's key, so you can't use datastore.Get() to get an entity, you have to use a query, e.g. datastore.NewQuery().

Comparision:

Pros of I. are that it's more compact, uses less datastore space, faster and easier to get entities by regnr.

Cons of I. are that you are responsible keeping regnr unique, and you can't save Car entities without regnr (which may or may not be a problem).

Upvotes: 2

Simon Guldstrand
Simon Guldstrand

Reputation: 488

I noticed that if I create a car by inserting the regnr as key like this:

car := &types.Car{
            Model:        req.Model,
            Regnr:        req.Regnr,
            Year:         req.Year,
            Type:         req.Type,
            CreationTime: time.Now(),
            Sold:         false,
        }
        //key := datastore.NewKey(context, "Car", "", 0, nil)
        carKey := datastore.NewKey(context, "Car", req.Regnr, 0, nil)
        _, err := datastore.Put(context, carKey, car)

I can find it by doing as I wrote in the question. But is this a good way of doing it? I plan on keeping the regnr unique anyway if it is neccesary.

Upvotes: 0

Related Questions