golang datastore get object

1 view
Skip to first unread message

Simon Nilsson Guldstrand via StackOverflow

unread,
Jan 2, 2016, 5:27:04 PM1/2/16
to google-appengin...@googlegroups.com

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!



Please DO NOT REPLY directly to this email but go to StackOverflow:
http://stackoverflow.com/questions/34570633/golang-datastore-get-object

Simon Nilsson Guldstrand via StackOverflow

unread,
Jan 2, 2016, 5:27:06 PM1/2/16
to google-appengin...@googlegroups.com

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.



Please DO NOT REPLY directly to this email but go to StackOverflow:
http://stackoverflow.com/questions/34570633/golang-datastore-get-object/34570731#34570731

icza via StackOverflow

unread,
Jan 2, 2016, 5:27:08 PM1/2/16
to google-appengin...@googlegroups.com

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

This line:

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

Creates a new, incomplete key. If you try to save an entity with an incomplete key, the datastore will assign a random, unique numeric ID to it. A numeric ID, not a string name.

And then you try to query 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 read my answer about entity identifiers: Can I use AllocateIDs as “string” ?



Please DO NOT REPLY directly to this email but go to StackOverflow:
http://stackoverflow.com/questions/34570633/golang-datastore-get-object/34571354#34571354

icza via StackOverflow

unread,
Jan 2, 2016, 5:37:04 PM1/2/16
to google-appengin...@googlegroups.com

You can't find the inserted entity, because it was saved with a different key than the one you try to find 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 query 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:

  • 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)
  • Or use a randomly assigned numeric ID, and simply have regnr as a "normal" property. This won't limit you in finding entities by regnr as you can filter entities by it if it's an indexed property.

icza via StackOverflow

unread,
Jan 2, 2016, 5:42:08 PM1/2/16
to google-appengin...@googlegroups.com

You can't find the inserted entity, because it was saved with a different key than the one you try to find 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 query 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 a randomly distributed numeric ID assigned automatically. 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().

icza via StackOverflow

unread,
Jan 2, 2016, 5:47:07 PM1/2/16
to google-appengin...@googlegroups.com

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

icza via StackOverflow

unread,
Jan 2, 2016, 5:52:04 PM1/2/16
to google-appengin...@googlegroups.com

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:

Reply all
Reply to author
Forward
0 new messages