I am new at golang. I am trying to write in a specific database schema using GORM and database/sql package.
Here is my struct
type Person struct {
gorm.Model
Name string
Age int
}
and my function to write in db is:
func writedb(){
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+" password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
db, err := gorm.Open("postgres", psqlInfo)
if err != nil {
panic(err)
fmt.Println("Não conectou-se ao BANCO DE DADOS")
}
defer db.Close()
db.AutoMigrate(&Person{})
//t := time.Now()
//ts := t.Format("2006-01-02 15:04:05")
db.Create(&Person{Name : "alex", Age: 20})
}
My db is structured like this
databaseName
--schemaPeople
--schemaVehicle
--schemaPublic
When I compile, the data inserted goes to an new table in public schema, I want to insert an row in people schema. What am I doing wrong? Am I declaring the struct wrong? How I set the specific schema??
In the gorm you can denote the schema in the TableName() method of your struct, for example:
type Person struct {
gorm.Model
Name string
Age int
}
func (Person) TableName() string {
return "people.persons"
}
Related
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
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")
Here is a screen shot of the entities I'm trying to read.
Entities
Here is my go code:
package readfromgcd
import (
"net/http"
"appengine"
"appengine/datastore"
"fmt"
)
type person struct {
firstname string
lastname string
}
func init () {
http.HandleFunc("/", readpeople)
}
func readpeople (w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
q := datastore.NewQuery("person")
people := make([]person, 0, 20)
if _, err := q.GetAll(c, &people); err !=nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
fmt.Fprint(w, "Hello world!")
}
I get the following result:
datastore: cannot load field "firstName" into a "readpeople.person": no such struct field
Here is a screenshot.
result
This code does not show doing anything with this data. I wanted to limit this post to the retrieval. I must be missing something simple. Where have I gone wrong? Thanks in advance for any help.
Property names in your datastore do not match field names in your Go struct person. For example in your datastore person has property firstName but your struct has field firstname.
So first thing is to make them match; or if you want to use different names in your Go struct, use struct tags to define the mappings.
Another important thing: you have to export your type and its fields in order so that the datastore package will be able to load data into it using reflection. So you have to start your type name and its fields with uppercase letters:
type Person struct {
FirstName string `datastore:"firstName"`
LastName string `datastore:"lastName"`
}
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)
I'm attempting to write a webapp in Go using the Google App Engine, and I have a question about modeling relationships using the datastore.
I know in Python I would be able to model a relationship using a db.referenceProperty(). What I can't seem to figure out is how to make a similar association using the Go APIs.
Has anyone had any luck with this?
You can use Key as a property in the entity: http://code.google.com/appengine/docs/go/datastore/reference.html
Something like this (I don't know Go so bear with me):
type Employee struct {
Name string
Boss *Key
}
employee := Employee{
Name: "John Doe",
Boss: key // a key to some other entity
}
Peter, you were definitely on the right track. I think I've figured this out. I haven't really tested this, but it appears to be right in the datastore viewer. What I have right now looks like this (ignoring error checking for the example):
type Boss struct {
Name, Uuid string
}
type Employee struct {
Name, Uuid string,
Boss *datastore.Key
}
boss := &Boss {
Name: "Pointy Haired Boss",
Uuid: <<some uuid>>,
}
dilbert := &Employee {
Name: "Dilbert",
Uuid: <<some uuid>>,
boss: nil,
}
datastore.Put(context, datastore.NewIncompleteKey(context, "Boss", nil), bossman)
query := datastore.NewQuery("Boss").Filter("Uuid =", bossMan)
for t := query.Run(ctx); ; {
var employee Employee
key, err := t.Next(&employee)
if err == datastore.Done {
break
}
if err != nil {
fmt.Fprintf(w, "Error %s", err)
}
dilbert.Boss = key
}
datastore.Put(context, datastore.NewIncompleteKey(context, "Employee", nil), dilbert)