In this code, I am trying to access the Cardname from the MongoDB database but it is giving me an empty string. Although it prints all the variables before Cardname but does not print the variables after Cardname and Cardname itself.
type UserCredentials struct {
Fname string
Lname string
Email string
Password string
Phone string
Country string
State string
Faddress string
Laddress string
Postal string
Company string
Cardname string
Cardnumber string
Expmonth string
Expyear string
}
func FindCard(email, password string) {
var uc UserCredentials
collection := Connect.Database("eCommerce").Collection("register")
if err := collection.FindOne(context.TODO(), bson.M{"email": email, "password": password}).Decode(&uc); err != nil {
log.Fatal(err)
}
fmt.Println(uc.Cardname)
}
The mongo driver will not magically find out which document field you want to set into which struct field.
There are some "common sense" rules, such as field names matching properties (even if the first letter is not capitalized), but the field name Cardname will not be matched with the property name "card name".
You have to tell the mapping using struct tags, namely the bson struct tag (this is what the mongo-go driver uses).
For example:
type UserCredentials struct {
Fname string
Lname string
Email string
Password string
Phone string
Country string
State string
Faddress string
Laddress string
Postal string
Company string
Cardname string `bson:"card name"`
Cardnumber string `bson:"card number"`
Expmonth string `bson:"expiry month"`
Expyear string `bson:"expiry year"`
}
Related
I have written a save function
let saveRecord(record: PostDataItem, coll: IMongoCollection<PostDataItem>, orderNumberToCheck: string) =
let filterDefinition = Builders<PostDataItem>.Filter.Eq((fun d -> d._id), record._id)
let update = Builders<PostDataItem>.Update.Set((fun f -> f.orderNumberToCheck),orderNumberToCheck)
let options = new UpdateOptions(IsUpsert=true)
let result = coll.UpdateOne(filterDefinition, update, options)
result
Unfortunately the result from MongoDB tells me that it found a match when trying to update, but it did not modify it ( matched=1, modified=0 ). The only unique thing about this is that the field "orderNumberToCheck" doesn't actually exist prior to this - but I assumed that upsert would take care of that. My type is below.
[<CLIMutable>]
type PostDataItem = {
_id: BsonObjectId
dateLodged: DateTime
productCode: string
productDescription: string
clientReference: string
manifestContract: string
client: string
quantity: string
unitPrice: string
gst: string
total: string
clientReference2: string
weight: string
reference1: string
ticketNumber: string
transactioncode: string
invoiceExplanationField1: string
invoiceExplanationField2: string
invoiceExplanationField3: string
invoiceExplanationField4: string
invoiceExplanationField5: string
invoiceExplanationField6: string
[<BsonDefaultValue(null)>]
orderNumberToCheck: string
[<BsonDefaultValue(null)>]
isUnique: Nullable<bool>
[<BsonDefaultValue(null)>]
expectedPrice: Nullable<decimal>
}
I've looked across Google and have found no answer to the below..
I'm looking to prepend a single String character to a list of numbers: A12345
In the example below I'm creating the class and when declaring an instance, setting the employeeNumber to 12345. Later on, when the property is called, I'd like it to return employeeNumber prepend with the letter p.
class Employee {
var surname: String
let forename: String
let employeeNumber: Int {
set {
"p\(employeeNumber)"
}
}
}
let employeeOne = Employee(surname: "Jones", forename: "Tom", employeeNumber: 12345)
employeeOne.employeeNumber // returns A12345
I appreciate that this code might be WELL off what I should be using (i.e using a setter?).
What you are looking for is a function (or a computed property) that returns a String value made of the employee number prefixed by a letter:
struct Employee {
var surname: String
var forename: String
var employeeNumber: Int
var employeeNumberAsString: String {
"A\(employeeNumber)"
}
}
let employee = Employee(surname: "Jones", forename: "Tom", employeeNumber: 12345)
print(employee.employeeNumberAsString)
// prints "A12345"
Your employee number is an Int, you can't set it with a String, use a property that stores the number and a function to retrieve the formatted number.
I am making rest API using go and echo, and I'm working on updating data. At first I was using struct to store the payload and then do the update to mongodb
type updatePayload struct {
FullName string `json:"fullName" bson:"fullName"`
FirstName string `json:"firstName" bson:"firstName"`
LastName string `json:"lastName" bson:"lastName"`
Location string `json:"location" bson:"location"`
Gender string `json:"gender" bson:"gender"`
State string `json:"state" bson:"state"`
Subdistrict string `json:"subdistrict" bson:"subdistrict"`
Address string `json:"homeAddress" bson:"homeAddress"`
Profession string `json:"provession" bson:"provession"`
Settings struct {
Email bool `json:"email" bson:"email"`
SMS bool `json:"sms" bson:"sms"`
GCM bool `json:"gcm" bson:"gcm"`
} `json:"settings" bson:"settings"`
Coordinates struct {
Type string `json:"type" bson:"type"`
Coordinates []float64 `json:"coordinates" bson:"coordinates"`
} `json:"coordinates" bson:"coordinates"`
}
The update is working but if I'm not send all the parameters like only send one field , the rest of the fields is updated to, only it was an empty string ""
is there any way I can only update the field that was specified on the request payload.
You have to specify omitempty on the struct
type PayloadUpdateProfile struct {
FullName string `json:"fullName,omitempty" bson:"fullName,omitempty"`
FirstName string `json:"firstName,omitempty" bson:"firstName,omitempty"`
LastName string `json:"lastName,omitempty" bson:"lastName,omitempty"`
}
Bind the payload into the struct as usual
var payload profile.PayloadUpdateProfile
err := c.Bind(&payload)
then convert it
var payloadInterface map[string]interface{}
inrecPayload, _ := json.Marshal(payload)
json.Unmarshal(inrec, &payloadInterface)
UpdateMethod(ctx, filter, payloadInterface)
You can do things like this:
type updatePayload struct {
FullName string `json:"fullName" bson:"fullName"`
FirstName string `json:"firstName" bson:"firstName"`
LastName string `json:"lastName" bson:"lastName"`
Location string `json:"location" bson:"location"`
Gender string `json:"gender" bson:"gender"`
State string `json:"state" bson:"state"`
Subdistrict string `json:"subdistrict" bson:"subdistrict"`
Address string `json:"homeAddress" bson:"homeAddress"`
Profession string `json:"provession" bson:"provession"`
Settings struct {
Email bool `json:"email" bson:"email"`
SMS bool `json:"sms" bson:"sms"`
GCM bool `json:"gcm" bson:"gcm"`
} `json:"settings" bson:"settings"`
Coordinates struct {
Type string `json:"type" bson:"type"`
Coordinates []float64 `json:"coordinates" bson:"coordinates"`
} `json:"coordinates" bson:"coordinates"`
}
func (payload *updatePayload) prepareUpdateQuery() (bson.M, error) {
updateQuery := make(bson.M)
if len(payload.FirstName) != 0 {
updateQuery["firstName"] = payload.FirstName
}
if len(payload.LastName) != 0 {
updateQuery["lastName"] = payload.LastName
}
// do same like above for other fields
updateQ := make(bson.M)
updateQ["$set"] = updateQuery
return updateQ, nil
}
have the method on updatePayload struct and after decoding the api payload , call this method and generate the update query for those fields only which has data from api payload. Once update query is made pass that update query to mongodb update wrapper function .
I have People and Data , where People has one Data and Data belongs to People
how to make a request body JSON for that Association in go gin? I am using gorm for this case,
the documentation of gorm is not clear for me for this case,
i was supposed like
func CreateTodo(db *gorm.DB) func(c *gin.Context) {
var person Person
var data Data
c.bindJSON(&Person)
c.bindJSON(&Data)
db.create(&Person)
db.create(&Data)
c.JSON(200, gin.H{ result : []interface{person, data})
}
type (
Data struct {
ID uint `gorm:"auto_increment"`
PersonID uint
Person *Person `gorm:"foreignkey:PersonID;association_foreignkey:id"`
Address string
Languange string
}
Person struct {
gorm.Model
Email string `gorm:"type:varchar(100);unique_index;not null"`
Password string `gorm:"type:varchar(100);not null"`
Role string `gorm:"size:30;not null"`
DataID uint
Data *Data `gorm:""foreignkey:DataID;association_foreignkey:id"`
}
)
I am sure it will not make the person_id and data_id for FK
what I ask, how I can make the request body for that Association until those request created with FK itself ? should I create then update again for person_id and data_id after it created ??
Gorm will do almost everything for an association link. It seems that "DataID" in your Person struct is useless. See the code below for an example:
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
type (
Data struct {
ID uint `gorm:"auto_increment"`
PersonID uint
Person *Person `gorm:"foreignkey:PersonID;association_foreignkey:id"`
Address string
Languange string
}
Person struct {
gorm.Model
Email string `gorm:"type:varchar(100);unique_index;not null"`
Password string `gorm:"type:varchar(100);not null"`
Role string `gorm:"size:30;not null"`
Data *Data `gorm:""foreignkey:PersonID;association_foreignkey:id"`
}
)
func main() {
db, err := gorm.Open("sqlite3", "test.db")
if err != nil {
panic("failed to connect database")
}
db.LogMode(true)
defer db.Close()
// Migrate the schema
db.AutoMigrate(&Person{}, &Data{})
data := &Data{
Address: "Shanghai,China",
Languange: "Chinese",
}
person := &Person{
Email: "zhjw43#163.com",
Data: data,
}
db.Save(person)
db.DropTable("data", "people")
}
I have the following code.
Handler
func (authHandler *AuthHandler) Login(c *gin.Context) {
var user models.User
c.Bind(&user)
if &user == nil {
c.BindJSON(&user)
}
userObject, err := authHandler.userRepo.FindBy(
models.User{
Email: user.Email,
},
)
if err != nil {
c.JSON(401, gin.H{"_message": "User not found."})
return
}
passErr := bcrypt.CompareHashAndPassword([]byte(userObject.Password), []byte(user.Password))
if passErr != nil {
c.JSON(401, gin.H{"_message": "Password incorrect."})
return
}
token, err := services.CreateToken(userObject)
if err != nil {
c.JSON(401, gin.H{"_message": "Password incorrect."})
return
}
c.JSON(200, gin.H{"token": token, "user": gin.H{
"id": &userObject.ID,
"first_name": &userObject.FirstName,
"last_name": &userObject.LastName,
"email": &userObject.Email,
"avatar": &userObject.Avatar,
"location": &userObject.Location,
"bg_img": &userObject.BgImg,
}})
}
Model
// user.go
type User struct {
ID string `gorm:"primary_key:true"`
FirstName string `form:"first_name" json:"first_name,omitempty"`
LastName string `form:"last_name" json:"last_name,omitempty"`
Password string `form:"password" json:"password" bindind:"required"`
Email string `gorm:"type:varchar(110);unique_index" form:"email" json:"email,omitempty" binding:"required"`
Location string `form:"location" json:"location,omitempty"`
Avatar string `form:"avatar" json:"avatar,omitempty"`
BgImg string `form:"bg_img" json:"bg_img,omitempty"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
}
func (repo *UserRepo) FindBy(params User) (User, error) {
var user User
err := repo.db.First(&user, "email = ?", params.Email).Error
fmt.Println(err)
if err != nil {
return user, err
}
return user, nil
}
I've tried doing the find in several different ways with no luck. I get a 401 response every time and the fmt.Prinlnt(err) in the model shows an record not found error.
So it turns out I needed to set the DeletedAt field to a null value. Under the hood, GORM automatically checks for a DeletedAt value. I.e SELECT * FROM users WHERE email = 'someone#gmail.com' AND deleted_at IS NULL. However, my DeletedAt fields were automatically being set to a blank date, which technically isn't NULL.
I added a struct...
type NullTime struct {
time.Time
Valid bool
}
Then updated my model...
type User struct {
ID string `gorm:"primary_key:true"`
FirstName string `form:"first_name" json:"first_name,omitempty"`
LastName string `form:"last_name" json:"last_name,omitempty"`
Password string `form:"password" json:"password" bindind:"required"`
Email string `gorm:"type:varchar(110);unique_index" form:"email" json:"email,omitempty" binding:"required"`
Location string `form:"location" json:"location,omitempty"`
Avatar string `form:"avatar" json:"avatar,omitempty"`
BgImg string `form:"bg_img" json:"bg_img,omitempty"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt NullTime
}
The convention in 'gorm' is to include the base model in your structs.
// Base Model definition from gomodel.go
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
// Your struct
type User struct {
gorm.Model
Name string
}
As you can see, 'gorm' expected a pointer to handle the NULL value.