Query without related objects - go

I have the following query:
db.Where("user_id = ?", tmpUser.ID).Find(&subscriptions)
subscriptions is a slice of the subscription object.
The problem is, it will output all subscriptions include the related objects (like the user object).
How can I query the database and get back only subscription records without the related (belongs to and has many) objects?

You can use the auto_preload setting:
db.Set("gorm:auto_preload", false).Where("user_id = ?", tmpUser.ID).Find(&subscriptions)
Or you can use the PRELOAD struct tag:
type Subscription struct {
ID uint
User User `gorm:"PRELOAD:false"`
UserID uint
}
https://gorm.io/docs/preload.html#Auto-Preloading

db.Find(&subscriptions). if you want count append .Count(&count) object

Related

Should I explicitly create a relation symmetrical to "Belongs To" or "Has Many"?

I am new to ORM (and GORM) so apologies if this is an obvious question, but it does not seem to be covered by the documentation.
I will be using the examples from the documentation as a base to my questions
Question 1: Belongs To
// `User` belongs to `Company`, `CompanyID` is the foreign key
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}
type Company struct {
ID int
Name string
}
A User belongs to one Company only → this is handled by the code
above
A Company has many User → is this implied by the code
above? Or should I add somehow a relation O2M in Company?
Question 2: Has Many
// User has many CreditCards, UserID is the foreign key
type User struct {
gorm.Model
CreditCards []CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
A User has 1+ CreditCard→ this is handled by the code
A CreditCard can belong to several users (say, a shared family CC) → is it implied? (if not: how to set up the O2M relationship).
Or is it, instead, a case where a CreditCard is explicitly configured to belong to only one user?
Q1: Based on how you defined your structs, you don't need an explicit O2M relationship in the Company struct, but when loading Company details, if you want to load all users that are assigned to that specific company, you need to add that field as well. It will need an additional function call like Preload or Joins, but you shouldn't need an explicit definition of this relationship.
type Company struct {
ID int
Name string
Users []User
}
Q2: The way the relationship is defined now, it is configured so that a CreditCard belongs to only one user. If you want a many2many relationship, you need to specify the relation table. There is more documentation on it here, but it should look something like this:
type User struct {
gorm.Model
CreditCards []CreditCard `gorm:"many2many:users_creditcards"`
}
type CreditCard struct {
gorm.Model
Number string
}

One-to-many associations not working with test entries

Similar to this question, but in the case of one-to-many: Associations not working with test entries
I have two models User and E-Mails in GORM defined: File user.go
type User struct {
gorm.Model
Identity string `json:"identity"`
Password string `json:"password"`
Emails []Email
}
type Email struct {
gorm.Model
UserID uint
Text string `json:"text"`
Sender string `json:"sender"`
}
According to the documentation this should work with a test entry:
userRec := &user.User{ Identity: "John Wayne", Password: "mysecretpassword", Emails: []user.Email{user.Email{Text: "My Text", Sender: "julia#world.me"}, user.Email{Text: "My Text", Sender: "julia#world.me"}}}
However, the Email entries do not get associated with the User object.
Is it normal that the User object does not have entries to which Email objects it is referring to (as opposed to the "refer to" case)?
How can I query a User with all the corresponding Email objects?
All Emails are available via
var emails[] Email
db.Where("user_id = ?", id).Find(&emails)
You need to Preload (eager load) the emails table, by referring to its column name:
user := &User{}
db.Preload("Emails").First(user)
If you are using one-to-one relations, you can also do it automatically by calling:
db.Preload(clause.Associations).Find(user)
Note: This will not work for one-to-many relations.
There is some other functionality supported, such as nested Preloading, and combining joins and preloads together (for the purpose of filtering or ordering on sub-tables) defined in the GORM Docs

What does Preload function do in gorm?

The link http://gorm.io/docs/preload.html talks about preloading in GORM, but I am unable to understand what this function does.
type User struct {
gorm.Model
Username string
Orders Order
}
type Order struct {
gorm.Model
UserID uint
Price float64
}
db.Preload("Username")
db.Preload("Orders").Find(&users)
Can someone explain what will these 2 statements do? What will be the output ?
Is it that preload is used to cache the results?
The link you provided shows what it does. You just have to actually read the information on the page.
First of all, this doesn't really do anything:
db.Preload("Username")
On the other hand, the following:
db.Preload("Orders").Find(&users)
Does do something. First it populates users and then it populates []user.Orders. On the comments on the page you linked you will find this, which shows what it does by query:
db.Preload("Orders").Find(&users)
//// SELECT * FROM users;
//// SELECT * FROM orders WHERE user_id IN (1,2,3,4);
So what does this really do? I can give you the technical answer, which you can easily find out by googling eager loading or I can give you an answer by example which I feel is simpler.
So let me explain this by example.
Say you have users, where each user can have multiple orders. This is a one to many relationship which can be defined like:
type User struct {
gorm.Model
Username string
Orders []Order
}
When you populate your users slice like:
db.Find(&users)
//// SELECT * FROM users;
If you need to get all the orders for each user you can easily access user.Orders but this would be empty anyway because it didn't get populated.
If we populate users slice like:
db.Preload("Orders").Find(&users)
The user.Orders will be populated by the orders of that user. This is an abstraction that makes dealing with relationships easier.
The ugly alternative would be:
db.Find(&users)
for user := range users {
db.Where("user_id", user.id).Find(&user.Orders)
}
It will also make more request to the database than necessary. (which is not good)
If your users has Posts and Comments and Orders then you can define and query it like this:
type User struct {
gorm.Model
Username string
Orders []Order
Comments []Comment
Posts []Post
}
db.Preload("Orders").Preload("Comments").Preload("Posts").Find(&users)
With just the code above you can now have access to the users data in different tables in the database.
I hope that helps.

GraphQL with apollo-client, Is it possible to have same id's and different typenames

I had a question and can't find it in documentation.
For example I have a list
products with ids 1,2,3,4
And I have another list, categories with ids 1,2,3,4.
example query
{
products {
id
name
categories {
id
name
}
}
}
We can see that they both have same ids but different typename inside apollo.
Will it create any problem while caching the data? As Apollo normalizes our data with the id's,
Help would be appreciated.
Apollo normalizes using both the __typename and id (or _id) fields, so having a Product and a Category with the same id will normally not cause any problems.
The client normally appends the __typename for every selection set in your query -- so you do not have to actually add the __typename field yourself.
The config object passed to InMemoryCache includes a addTypename property, which defaults to true. If you set this to false, then the __typename field will not be added and you will see issues with the cache in this scenario unless you have universally unique IDs.

How to use same generated ID in two fields prisma-graphql

I'm implementing a graphql prisma datamodel. Here I have a type called BankAccount . I may need to update and delete them as well. I'm implementing this as immutable object. So, when updating I'm adding updating the existing record as IsDeleted and add a new record. And when updating an existing record I need to keep the id of the previous record to know which record is updated. So, I've came up with a type like this
type BankAccount {
id: ID! #unique
parentbankAccount: String!
bankName: String!
bankAccountNo: String!
isDeleted: Boolean! #default(value: "false")
}
Here the parentBankAccount keeps the id of previous BankAccount. I'm thinking when creating a bank account, setting the parentBankAccount as same as the id as it doesn't have a parent. The thing is I'm not sure it's possible. I'm bit new to GraphQL. So, any help would be appreciated.
Thanks
In GraphQL, generally if one object refers to another, you should directly refer to that object; you wouldn't embed its ID. You can also make fields nullable, to support the case where some relationship just doesn't exist. For this specific field, then, this would look like
type BankAccount {
parentBankAccount: BankAccount
...
}
and that field would be null whenever an account doesn't have a parent.
At an API level, the layout you describe seems a little weird. If I call
query MyBankAccount {
me { accounts { id } }
}
I'll get back some unique ID. I'd be a little surprised to later call
query MyBalance($id: ID!) {
node(id: $id) {
... on BankAccount {
name
isDeleted
balance
}
}
}
and find out that my account has been "deleted" and that the balance is from a week ago.
Using immutable objects in the underlying data store makes some sense, particularly for auditability reasons, but that tends to not be something you can expose out through a GraphQL API directly (or most other API layers: this would be equally surprising in a REST framework where the object URL is supposed to be permanent).

Resources