How to do many-to-many Find query - postgresql

I have two structs with a many-to-many relation like this:
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
I want to find users who have specified language. something like this:
var users []User
var lang = Language <-- this is the specified language
db.Model(&user).Association("Languages").Where("id = ? ", lang.ID).Find(&users)
but this format is not allowed.

I found the solution myself. for finding Users who have specified language must use Back-Reference like this:
type User struct {
gorm.Model
Languages []*Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
Users []*User `gorm:"many2many:user_languages;"`
}
and the query will be in this form:
var users []User
var lang = Language <-- this is the specified language
db.Model(&lang).Association("Users").Find(&users)

Related

How to work with has many relation in gorm?

import (
"gorm.io/gorm"
"gorm.io/driver/postgres"
)
type School struct {
gorm.Model
Students []Student `json:"students"`
}
type Student struct {
gorm.Model
Name string `json:"name"`
}
func init() {
//connect to db first
conn, err := gorm.Open(postgres.New(postgres.Config{
DSN: dbUri,
PreferSimpleProtocol: true,
}), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
db = conn
db.AutoMigrate(&Student{}, &School{})
}
Create the structs and automigrating it gives me an error. Do you know why this is? Also how to you work with has many relation in gorm, what kind of data does it create in postgres?
Error -
Need to define a valid foreign key for relations or it need to implement the Valuer/Scanner interface
You need to add a SchoolID field to your Student. See the docs here for full usage.
type Student struct {
gorm.Model
SchoolID uint
Name string `json:"name"`
}
To answer the second part, it will create two tables for you. Schools and students. The students will have a foreign key that points to the ID of a school. I would read the docs to learn how this works more.

Using an opaque ID type in place of primitive.ObjectID

In a db package, I don't want to expose MongoDB's primitive.ObjectID type as part of its public API. Instead, I want to define type Id interface{} within the db package and expose that. Since the driver doesn't know how to transform the database's ObjectID type into my custom ID type, I registered a type decoder like so:
type Id interface{}
var idType = reflect.TypeOf((*Id)(nil)).Elem()
type User struct {
Id `bson:"_id,omitempty"`
}
func main() {
reg := bson.NewRegistryBuilder().
RegisterTypeDecoder(idType, bsoncodec.ValueDecoderFunc(idDecodeValue)).
Build()
client, err := mongo.Connect(context.TODO(), options.Client().
ApplyURI("...").
SetRegistry(reg))
coll := client.Database("...").Collection("...")
var u0 User
coll.InsertOne(context.TODO(), u0)
var u1 User
coll.FindOne(context.TODO(), bson.D{}).Decode(&u1)
}
func idDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.IsValid() || val.Type() != idType {
return bsoncodec.ValueDecoderError{
Name: "IdDecodeValue",
Types: []reflect.Type{idType},
Received: val,
}
}
oid, _ := vr.ReadObjectID()
val.Set(reflect.ValueOf(oid))
return nil
}
I saw that there exists a bsoncodec.NewEmptyInterfaceCodec() to use in place of idDecodeValue, but that only seems to work when User.Id's type is exactly interface{}. I wrote idDecodeValue based off of the existing codecs, but I'm not entirely sure what's going on (mostly due to not knowing when val.IsValid() would ever return false). Is all of this the best, most idiomatic way to go about supporting a custom ID type?

extracting nested struct data from mongodb

Have a struct as follows
type Person struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string `json:"name"`
Phone string `json:"phone"`
}
and then want to nest it in another struct
type Customer struct {
ID bson.ObjectId `bson:"_id,omitempty"`
StoreName string
Person Person `json:"persons"`
}
instantiated as
customer := Customer{bson.NewObjectId(), "Seattle", p1}
and insterted into Mongo db (I am using the mgo driver for golang)
err = databaseConnection.Insert(&customer)
How do I retrieve the customer struct from the DB using parameters from the nested Person struct? E.g. pull all Customer structs that have a Person struct named “John”
I am trying
err = databaseConnection.Find(bson.M{XXXXXXXXX}).All(&resultsB)
but I can’t figure out what XXXXXX should be.
You could try something like that: bson.M{"person.name": "john"}
check mongodb documentation on embedded documents: https://docs.mongodb.com/manual/tutorial/query-embedded-documents/

Apollo iOS codegen: Nested use of a fragment in a mutation creates unexpected property types in Fragments struct

I have the following fragment:
fragment User on UserResponse {
firstName
lastName
emailAddress
emailConsent
phoneNumber
}
When used as root in a mutation, the code generation will correctly generate a root User struct in API.swift and use that struct as the type of user properties in Fragments
Eg.:
mutation updateUserYourInformation($phoneNumber: String!, $emailConsent: Boolean!) {
updateUser(phoneNumber: $phoneNumber, emailConsent: $emailConsent) {
...User
}
}
and
mutation addRelations($spouse: Boolean!, $children: Int!, $roomMates: Int!) {
addRelations(spouse: $spouse, roommates: $roomMates, children: $children) {
...User
}
}
will generate mutations where both UpdateUserYourInformationMutation.Data.UpdateUser.Fragments and AddRelationsMutation.Data.AddRelation.Fragments has a user property of the same struct type User.
However, when nesting the fragment in a mutation it generates a nested User struct within the Mutation struct, which will be the type of the user property in the generated nested Fragments struct. E.g:
mutation exchangePin($email: String!, $pin: String!) {
exchangePinForToken(email: $email, pin: $pin) {
valid
user {
...User
}
authToken
remainingAttempts
}
}
will generate ExchangePinMutation.Data.ExchangePinForToken.User and ExchangePinMutation.Data.ExchangePinForToken.User.Fragments structs. However, the user property of ExchangePinMutation.Data.ExchangePinForToken.User.Fragments is of type ExchangePinMutation.Data.ExchangePinForToken.User and not of type User, as I would have expected.
Consequently, the types differ and in order to update the current User object in my app, I have to take the snapshot of ExchangePinMutation.Data.ExchangePinForToken.User and initialise a new User object using that: E.g:
...
let userSnapshot = data.exchangePinForToken.user?.snapshot
Session.currentUser = User(snapshot: userSnapshot)
...
Maybe I'm just creating my fragments and or mutations wrong?
The problem is that the user property of the ExchangePinMutation.Data.ExchangePinForToken.User.Fragments struct should be of the User fragment type, but the type is shadowed by the local ExchangePinMutation.Data.ExchangePinForToken.User type.
I fixed my issue by renaming the User fragment to UserFull and creating a typealias: typealias User = UserFull
Almost no refactoring needed!
https://github.com/apollographql/apollo-codegen/issues/394#issuecomment-373323235

Trying to convert string to instance variable

I'm new to GO language.
Trying to learn GO by building real web application.
I'm using revel framework.
And here is my resource routes:
GET /resource/:resource Resource.ReadAll
GET /resource/:resource/:id Resource.Read
POST /resource/:resource Resource.Create
PUT /resource/:resource/:id Resource.Update
DELETE /resource/:resource/:id Resource.Delete
for example:
GET /resource/users calls Resource.ReadAll("users")
And this is my Resource controller (it's just a dummy actions for now):
type Resource struct {
*revel.Controller
}
type User struct {
Id int
Username string
Password string
}
type Users struct {}
func (u Users) All() string {
return "All"
}
func (c Resource) ReadAll(resource string) revel.Result {
fmt.Printf("GET %s", resource)
model := reflect.New(resource)
fmt.Println(model.All())
return nil
}
I'm trying get instance of Users struct by converting resource string to object to call All function.
and the error:
cannot use resource (type string) as type reflect.Type in argument to
reflect.New: string does not implement reflect.Type (missing Align
method)
I'm new to GO please don't judge me :)
Your problem is here:
model := reflect.New(resource)
You can't instantiate a type from a string that way. You need to either use a switch there and do stuff depending on the model:
switch resource {
case "users":
model := &Users{}
fmt.Println(model.All())
case "posts":
// ...
}
Or use reflect correctly. Something like:
var types = map[string]reflect.Type{
"users": reflect.TypeOf(Users{}) // Or &Users{}.
}
// ...
model := reflect.New(types[resource])
res := model.MethodByName("All").Call(nil)
fmt.Println(res)