Reputation: 488
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
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
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:
regnr
as string nameEither 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)
regnr
as "normal" propertyOr 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()
.
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
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