fisker
fisker

Reputation: 1039

Datastore - How to put Key inside Struct ID (golang)?

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

Upvotes: 3

Views: 1584

Answers (1)

icza
icza

Reputation: 418645

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

Upvotes: 2

Related Questions