How to create a data model using Go's dataStore? - google-app-engine

I've created a series of structs based on the way I would create tables in mySQL:
type User struct {
UserID int
Email string
Password string
DateCreated time.Time
}
type Device struct {
DeviceID int
Udid string
DateCreated time.Time
DateUpdated time.Time
IntLoginTotal int
}
type DeviceInfo struct {
DeviceID int
DeviceName string
Model string
LocalizedModel string
SystemName string
SystemVersion string
Locale string
Language string
DateCreated time.Time
}
However, I have the impression that I will not be able to make requests like this, and instead I need to create a single struct that can contain an array of multiple devices (each containing an array of multiple device info records).
What is the best way to go about doing this?

In this case, just set the "Kind" as the name of the struct.
From the docs:
func NewKey(c appengine.Context, kind, stringID string, intID int64, parent *Key) *Key
NewKey creates a new key. kind cannot be empty. Either one or both of
stringID and intID must be zero. If both are zero, the key returned is
incomplete. parent must either be a complete key or nil.
For example to save a User.
c := appengine.NewContext(r)
u := &User{UserID: userid, Email: email, Password: password, DateCreated: datecreated}
k := datastore.NewKey(c, "User", u.UserID, 0, nil)
e := p
_, err := datastore.Put(c, k, e)
Follow the same logic to save a different struct type.
To load a user:
c := appengine.NewContext(r)
k := datastore.NewKey(c, "User", userid, 0, nil)
e := new(User)
_, err := datastore.Get(c, k, e)

Related

change user status from capture to activated in mongoDB

Here, all i am trying to achieve is to change a user status from CAPTURE to ACTIVATED in the mongodb using golang. This is what i have done so far but yet i am not getting the right response.
So far, I have tried the following implementation but nothing happened... All i am expecting is to see a change on an existing user status.
func UpdateUserActivate(client *mongo.Client, user models.User) (*models.User, error) {
collection := client.Database("coche").Collection("user_entity")
_id, err := primitive.ObjectIDFromHex(user.ID)
if err != nil {
fmt.Println(err)
}
filter := bson.M{"_id": _id}
update := bson.M{"$set": bson.M{user.Status: "ACTIVATED"}}
_, _err := collection.UpdateOne(context.TODO(), filter, update)
if _err != nil {
return &user, errors.New("user activation failed")
}
return &user, nil
}
This is my user model.
type User struct {
gorm.Model
ID string `_id`
FirstName string `json:"firstName"bson:"firstname"`
LastName string `json:"lastName" bson: "lastname"`
Address string `json:"address" bson: "address"`
PhoneNumber string `json:"phoneNumber" bson: "phonenumber"`
Status string `json:"status" bson: "status"`
Email string `gorm:"unique" json:"email" "email"`
Password string `json:"password""password"`
Category string `json:"category" "category"`
Roles []string `json:"roles" "roles"`
}
Try update := bson.D{{"$set", bson.D{{"status": "ACTIVATED"}}}}
After "$set" use a comma ","
bson.M or bson.D shouldn't matter in that case. Just take care of the curly brackets using the one or the other.
Ref: https://www.mongodb.com/docs/drivers/go/current/usage-examples/updateOne/

Unable to get the record based on struct value from datastore using golang

I am writing a service for search functionality. when i am passing values in the body to get the specific record i am unable to get it based on the struct value.
ex:phone number or username
Edit1:
type PatientData struct {
ID int64 datastore:"-"
FirstName string json:"firstname,omitempty"
LastName string json:"lastname,omitempty"
UserName string json:"username,omitempty"
Phone string json:"phone,omitempty"
}
I want to get the full struct values based on Username or Phone. Below is my code:
func searchValue (res http.ResponseWriter, req *http.Request){
log.Printf("%#v Getting values url - x ", "called search")
patient := &PatientData{}
if err := json.NewDecoder(req.Body).Decode(patient); err != nil {
panic(err)
}
ctx := appengine.NewContext(req)
ctx, err := appengine.Namespace(ctx, NAMESPACENAME)
if err != nil {
panic(err)
}
m := patient.Phone
i, err := strconv.ParseInt(m, 10, 64)
log.Printf("%#v Getting values m ", m)
log.Printf("%#v Getting values url -yyy ",i)
key := datastore.NewKey(ctx, "Patient","" , i, nil)
log.Printf("%#v Getting values url - key ", key)
err = datastore.Get(ctx, key, patient)
if err := json.NewEncoder(res).Encode(patient); err != nil {
panic(err)
}
}
As i am passing PHONE in my Newkey i am unable to generate the values based on PHONE
I don't want to use Newkey in put functionality to generate a keyname and based on that KEYNAME i dont want to get Values.
datastore.Get() can only be used to get an entity from the datastore by its key, so its key must be known / present.
This is obviously not what you're trying to do. You are trying to fetch entities by properties which are not the key. To do that, you need to run a query.
Datastore queries are represented by the datastore.Query type. You need to create a query and set filters on it. In your case, you want to filter by the username and/or phone properties.
This is how it could look like. Fetch patient entities filtered by phone:
q := datastore.NewQuery("Patient").Filter("phone =", patient.Phone)
var patients []*Patient
keys, err := q.GetAll(ctx, &patients)
if err != nil {
// Handle error
return
}
// patients contains patients with the given phone number
An example fetching patients filtered by phone number AND user name:
q := datastore.NewQuery("Patient").
Filter("phone =", patient.Phone).
Filter("username =", patient.UserName)
var patients []*Patient
keys, err := q.GetAll(ctx, &patients)
if err != nil {
// Handle error
return
}
// patients contains patients with the given phone number and username

Beego: orm Read() vs orm RelatedSel()

Supposing I have the following structs defined:
type User struct {
Id int `orm:"pk;auto"
Username string `orm:"size(64);unique"`
Email string `orm:"size(255);unique"`
Password string `orm:"size(64)"`
Profile *Profile `orm:"rel(one);on_delete(cascade)"`
}
type Profile struct {
Id int `orm:"pk;auto"`
User *User `orm:"reverse(one)"`
Description string `orm:"size(255)"`
}
How much can my application be affected in terms of performance if I do a cascaded query directly when I just need the info present in the first struct (User.Id, User.Password, User.Email, or User.Username)?
Basically do:
o := orm.NewOrm()
user := &User{}
err := o.QueryTable("user").Filter("Username", username).RelatedSel().One(user)
Instead of
o := orm.NewOrm()
user := &User{Username: username}
err := o.Read(user, "username")

Update Entity Appengine Datastore with Go

I'm trying to find an effective example in how to perform updates on appengine datastore with Go.
All the examples I've found on the web are very vague and mostly explains concepts and not the "real life".
The appengine documentation for go says:
..."Updating an existing entity is a matter of performing another Put() using the same key."
My problem here is being in how to retrieve the key. So I have the code below to store and retrieve data:
func subscribe(w http.ResponseWriter, r *http.Request) {
user := User {
Name: r.FormValue("username"),
Email: r.FormValue("useremail"),
Flag: 0,
}
c := appengine.NewContext(r)
//datastore.Put(c, datastore.NewIncompleteKey(c, "User", nil), &user)
datastore.Put(c, datastore.NewKey(c, "User", "stringID", 0, nil), &user)
template.Must(template.ParseFiles("confirmation.html")).Execute(w, nil)
}
func checkusers(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
qUsers := datastore.NewQuery("User")
var users []User
qUsers.GetAll(c, &users)
template.Must(template.ParseFiles("users.html")).Execute(w, users)
}
How do I do an update on the flag property changing its value tom 1?
I'm a bit confused on this thing as I couldn't fully understand how the "key" is stored for each entity.
Any help would be very appreciated.
todo an update you first need to identify if your object is a new or an old one.
this can be simple done by adding the following method to your User struct:
type User struct {
Name string
Email string
Flag int64 `datastore:"-"`
}
func (u *User) IsNew() bool {
return u.Flag == 0
}
this tells data-store to ignore the Flag field when storing and retrieving an object
and because initial value of int64 is zero, a newly created object can be identified if Flag is zero
so creating a new object just needs to set UserName and Email:
user := User {
Name: r.FormValue("username"),
Email: r.FormValue("useremail")
}
then next step is to either use a IncompleteKey or a Key, for the put statement
could look like this:
var k *datastore.Key
if user.IsNew() {
k = datastore.NewIncompleteKey(c, "Users", nil)
} else {
k = datastore.NewKey(c, "Users", "", user.Flag, nil)
}
k, err := datastore.Put(c, k, user)
if err != nil {
return k, err
}
with an incomplete key, app-engine will generate a new key for you.
after put you can assign the new key to your object:
user.Flag = k.IntID
now if you do a query later you need to assign the Id to your query result objects,
the query will return the keys of query result in the same order so you can change your code like this:
keys, err := q.GetAll(c, &users)
if err != nil {
return
}
l := len(users)
for i := 0; i < l; i++ {
users[i].Flag = keys[i].IntID()
}
thats all, for more information, just have a look a the reference document there is explained with methods return which values.
https://developers.google.com/appengine/docs/go/datastore/reference

Golang GAE - intID in struct for mustache

Here is an Example of the app. The essential code is in: golang-code/handler/handler.go (After the subject should appear an ID!)
Im trying to build a little blog system in Golang on Google Appengine and use Mustache as template engine.
So, i have a struct:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
}
The data is passed to GAE via
datastore.Put(c, datastore.NewIncompleteKey(c, "Blogposts", nil), &blogposts)
So, GAE assigns automatically a intID (int64).
Now I tried to get the latest blogposts
// Get the latest blogposts
c := appengine.NewContext(r)
q := datastore.NewQuery("Blogposts").Order("-Date").Limit(10)
var blogposts []Blogposts
_, err := q.GetAll(c, &blogposts)
Until there all things works fine, but when I try to access intID (or stringID, whatever) I dont have access to this :-(
<h3>{{{PostTitle}}}</h3>
(PostTitle works, intID not, i've tried thousand of things, nothing worked :-( )
Anyone an idea? This would be great!
Edit:
I use mustache.
http://mustache.github.com/
In the code I use:
x["Blogposts"] = blogposts
data := mustache.RenderFile("templates/about.mustache", x)
sendData(w, data) // Equivalent to fmt.Fprintf
And then the data can be accessed in the .mustache template with {{{Content}}} or {{{PostTitle}}} etc.
As hyperslug pointed out, the id field of an entity is on the key, not the struct it gets read into.
Another way around this is to add an id field to your struct and tell datastore to ignore it, eg:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
Id int64 `datastore:"-"`
}
You can then populate the Id field manually after a call to GetAll() like so
keys, err := q.GetAll(c, &blogposts)
if err != nil {
// handle the error
return
}
for i, key := range keys {
blogposts[i].Id = key.IntID()
}
This has the benefit of not introducing an extra type.
intID is an internal property of a Key not the struct, and is accessible through a getter:
id := key.IntID()
GetAll returns []*Key, which you're not using:
_, err := q.GetAll(c, &blogposts)
One way to get around this is to create a viewmodel struct that has both your post and key info (untested, but this is the gist of it):
//... handler code ...
keys, err := q.GetAll(c, &blogposts)
if err != nil {
http.Error(w, "Problem fetching posts.", http.StatusInternalServerError)
return
}
models := make([]BlogPostVM, len(blogposts))
for i := 0; i < len(blogposts); i++ {
models[i].Id = keys[i].IntID()
models[i].Title = blogposts[i].Title
models[i].Content = blogposts[i].Content
}
//... render with mustache ...
}
type BlogPostVM struct {
Id int
Title string
Content string
}
I know this question is a couple years old, but the following article was very helpful to me in this regard: Golang basics with Google Datastore.
In the article, the author provides a nice example of how you can run a query that gets an entity by its ID...
func GetCategory(c appengine.Context, id int64) (*Category, error) {
var category Category
category.Id = id
k := category.key(c)
err := datastore.Get(c, k, &category)
if err != nil {
return nil, err
}
category.Id = k.IntID()
return &category, nil
}
...as well as getting a list/collection of entities with their associated ID:
func GetCategories(c appengine.Context) ([]Category, error) {
q := datastore.NewQuery("Category").Order("Name")
var categories []Category
keys, err := q.GetAll(c, &categories)
if err != nil {
return nil, err
}
// you'll see this a lot because instances
// do not have this by default
for i := 0; i < len(categories); i++ {
categories[i].Id = keys[i].IntID()
}
return categories, nil
}
The snippet above is very close to the helpful answer by #koz.
AFAICS, the Blogposts struct has no field intID, but it has a field PostTitle. I guess that could be the reason why the former doesn't and the later does get rendered, though I've never used Mustache...

Resources