Experimental somewhat ORM library for working with appengine datastore
.
$ go get -u github.com/drborges/datastore-model
Embed db.Model
to your model to add db.Datastore
support:
type Tag struct {
db.Model
Name string
Owner string
}
The model above, will be mapped to a datastore table named Tag
derived from the struct's name and its datastore key is
auto generated as:
datastore.NewKey(context, "Tag", "", 0, nil)
Struct tags
are available to override the behavior above.
Just tag the embedded type db.Model
with db:"Tags"
, like so:
type Tag struct {
db.Model `db:"Tags"`
Name string
Owner string
}
The key kind will be extracted from the tag, and the resulting key will look like:
datastore.NewKey(context, "Tags", "", 0, nil)
By tagging either a string or an integer field with db:"id"
, db.Datastore
will use it to create the entity's key.
type Tag struct {
db.Model `db:"Tags"`
Name string `db:"id"`
Owner string
}
Consider the model below for the following examples.
type Tag struct {
db.Model `db:"Tags"`
Name string `db:"id"`
Owner string
}
// This is a convenient way to group
// queries for a given entity
type Tags []*Tag
func (this Tags) ByOwner(owner string) *db.Query {
return db.From(new(Tag)).Filter("Owner=", owner)
}
The following code creates a new Tag
in the Tags
datastore entity:
tag := new(Tag)
tag.Name = "golang"
tag.Owner = "Borges"
err := db.NewDatastore(context).Create(tag)
Upon success the given entity has its key assigned to it, allowing you to access it by tag.Key()
.
The following code creates multiple entities Tag
in a single batch:
golang := new(Tag)
golang.Name = "golang"
appengine := new(Tag)
appengine.Name = "appengine"
err := db.NewDatastore(context).CreateAll(golang, appengine)
All created entities will have their respective keys assigned back to them upon success.
The following code updates a Tag
in the Tags
datastore entity:
tag := new(Tag)
tag.Name = "golang"
tag.Owner = "Borges"
err := db.NewDatastore(context).Update(tag)
Upon success the given entity has its key assigned to it, allowing you to access it by tag.Key()
.
The following code updates multiple entities Tag
in a single batch:
golang := &Tag{Name: "golang"}
appengine := &Tag{Name: "appengine"}
err := db.NewDatastore(context).UpdateAll(golang, appengine)
All entities have their keys set to themselves upon success.
The following code loads data from datastore into a Tag
:
tag := new(Tag)
tag.Name = "golang"
err := db.NewDatastore(context).Load(tag)
// tag.Owner is populated with data
The following code loads data from datastore into a Tag
:
golang := &Tag{Name: "golang"}
datastore := &Tag{Name: "datastore"}
err := db.NewDatastore(context).LoadAll(golang, datastore)
The following code deletes an existent entity from datastore:
tag := new(Tag)
tag.Name = "golang"
err := db.NewDatastore(context).Delete(tag)
Warning This API is still experimental and lots of changes might and likely will occur :)
The following code deletes multiple entities from datastore in a single batch:
err := db.NewDatastore(context).DeleteAll(tag1, tag2)
The following code runs a given query and maps the matched items to a list of entities, setting their keys behind the seems.
tags := Tags{}
err := db.NewDatastore(context).Query(tags.ByOwner(owner)).All(&tags)
For any given tag
in the tags
slice, one can access its key through tag.Key()
The following code runs a given query and loads the first item into the given entity instance.
tag := new(Tag)
err := db.NewDatastore(context).Query(Tags{}.ByOwner(owner)).First(tag)
This is still another experiment. In order to reduce the hassle of implementing memcached operations on datastore we implemented CachedDatastore
that abstracts that logic away.
CachedDatastore
embeds the regular Datastore
type only overriding some of its operations in order to add support to memcache
.
Currently the operations supporting memcache
are: Load
, Create
, Update
and Delete
.
Be aware if you use CachedDatastore
as your default datastore access interface, using any operation other than the ones mentioned above there will not be caching going on.
type MembershipCard struct {
db.Model
Number int `db:"id"`
Owner string
}
cds := db.CachedDatastore{db.NewDatastore(c)}
card := &MembershipCard{Number: 1}
cds.Create(card)
cardFromCache := &MembershipCard{Number: 1}
err := cds.Load(cardFromCache)
CachedDatastore
uses by default the encoded entity's key (card.StringId()
) as the memcache key.
One can tag a particular struct string
field to be used as cache key as follows:
type MembershipCard struct {
db.Model
Number int `db:"id"`
Owner string `cache:"id"`
}
cds := db.CachedDatastore{db.NewDatastore(c)}
card := &MembershipCard{Owner: "Borges", Number: 1}
cds.Create(card)
cardFromCache := &MembershipCard{Owner: "Borges"}
err := cds.Load(cardFromCache)
This is a very experimental project and there is a lot that can be done (iterator queries for instance...). This current work is essentially driven by BearchInc's use cases, though it is not restricted to them. Feel free to suggest and contribute.