3

I'm trying to build a many to many relationship, so I have 3 structs:

type Orders struct {
  ID int64
  CustomerID string
  etc
}

type Products struct {
  ID int64
  Name string
  Description string
  etc
}

type OrderDetails struct {
  OrderID int64
  ProductID string
  Quantity int
}

I believe this is the right way to do it, but my problem now is that I do not know how to put the datastore key inside the struct ID without making two client.Put requests because as far as I can tell, datastore.IncompleteKey("Products", nil) will not return the new key value until after you put it..

I guess some people would recommend using key *datastore.Key instead of ID int64, but I would prefer to convert the key to an ID

Any help would be much appreciated

1 Answer 1

2

One option is to allocate keys in advance, which you can set in your structs prior to calling Client.Put().

You can allocate IDs with the Client.AllocateIDs(). You can pass a slice of incomplete keys to it, and you get back a slice of complete datastore.Keys, which the datastore reserves for you (and thus guarantees not to "give out" to others or use when saving entities with incomplete keys). You can access the numeric IDs of the allocated keys in the Key.ID field.

But storing the numeric Key ID in the entities is redundant, and I find it a waste (of resources). Whenever you load an entity e.g. with Client.Get(), or multiple with Client.GetAll(), you also get back the keys, and you can fill the numeric IDs in the structs "manually" as a post-processing step. You can also wrap this post-processing functionality in a function which does this for you whenever you get entities from the datastore.

For example, if you have an OrderDetails entity loaded, which contains the OrderID, you may use datastore.IDKey() to construct the datastore.Key for the respective Order entity. Example doing it:

var orderDetails OrderDetails
// Load orderDetails

orderKey := datastore.IDKey("order", orderDetails.OrderID, nil)
// Now you have the key for the Order entity

var order Order
err := client.Get(ctx, orderKey, &order)

Which means you shouldn't store the "self ID" in the entities, you can construct datastore.Key values if the numeric ID is known.

Also see related question: Can I use AllocateIDs as "string" ? datastore

Sign up to request clarification or add additional context in comments.

4 Comments

Wow, exactly what I needed.. thanks a lot <3.. but I'm really curious about why it's a waste, I mean in the above example, if you do Client.GetAll() on OrderDetails, then how can you get Orders and Products if you don't store any OrderID and ProductID?
@fisker You may use datastore.IDKey() to construct a datastore.Key from a numeric ID. See edited answer, added an example.
Ahh, I think I understand.. so if I want to keep having the ID field for Orders and Products (to display the ID in the web application) then I should add datastore:"-" so it doesn't waste datastore resources, and before returning the var order Order struct (after doing client.Get(ctx, orderKey, &order)) I can set order.ID = orderKey.ID?
@fisker Exactly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.