I want to order records with associated records in GORM V2.
I have two structs:
type Client struct {
gorm.Model
UUID uuid.UUID `gorm:"type:uuid"`
ClientProfile ClientProfile
}
type ClientProfile struct {
gorm.Model
ClientID uint
FirstName string
LastName string
}
Now, I can load all the records with:
db.
Preload(clause.Associations).
Find(&clients).
How can I now order these records with a field from the ClientProfile struct?
I tried without success:
db.
Preload(clause.Associations).
Order("client_profiles.last_name DESC").
Find(&clients)
This throws the following error:
ERROR: missing FROM-clause entry for table "client_profiles" (SQLSTATE 42P01)
Find with Preload queries the clients table first, and then queries the client_profiles table with the IDs from the first, thus it can't sort the first query by data from the second one.
Since this is a HasOne relationship you can use Joins Preloading which actually does use a single query for both entities. Then you will be able to sort by the related entity's field:
err := db.
Model(&Client{}).
Joins("ClientProfile").
Order("client_profiles.last_name DESC").
Find(&clients).
Error
// handle error
Related
For a table, say details, with the schema as,
Column
Type
name
string
desc
map<int, string>
How do I form a select query - to be run by java program - which expects the result set in this structure?
name
desc
Bob
{1,"home"}
Alice
{2,"office"}
Having in mind limitations in impala with regards to complex types here
The result set of an Impala query always contains all scalar types;
the elements and fields within any complex type queries must be
"unpacked" using join queries.
ie. select * from details; would only return results without the column with map type(complex type).
The closest I've come up with is select name, map_col.key, map_col.value from details, details.desc map_col;. Result set is not in expected format - obviously
.
Thanks in advance.
Is it possible in GORM to give Create() a Struct A as input and store the result in Struct B?
I haven't found anything suitable in the documentation or on the internet.
The background is as follows:
I let Postgres create the fields id, createdAt and updatedAt - therefore they should not be part of the input Struct A (quasi the DTO/DAO).
However, in the result of Create() these fields are then present - so they should be parsed into Struct B, which contains all the fields of the table.
Problem if id, createdAt and updatedAt are not explicitly set:
Go initialises fields of structs that are not explicitly defined with default values, depending on the data type (0, nil etc.).
For the id of type UUIDv4, the value is then 00000000-0000-0000-0000000000.
Apparently this passed value then overwrites Postgres' gen_random_uuid() value for the id column.
Once this works fine, then a duplicyte key error occurs.
createdAt and updatedAt, on the other hand, seem to be generated correctly by Postgres, although I have found Go's default values there as well.
Thank you!
PS: Of course, I could simply create a UUID and give it to the database, but I am basically interested in whether or not my intention can be realised with GORM.
You don't need two separate structs, you can use your model to insert/fetch. One way of doing it is to embed gorm.Model, which will embed
// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
Embedding into User struct.
type User struct {
gorm.Model
Name string
Age int
}
// equals
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Name string
Age int
}
Now creating records
user := User{Name: "randomname", Age: 18}
result := db.Create(&user) // pass pointer of data to Create
user.ID // returns inserted data's primary key
user.CreatedAt // returns inserted data's created at key
user.UpdatedAt // returns inserted data's updated at key
Embedding gorm.Model is optional, you can embed it or add the fields to the struct directly or you can create your own struct to embed.
Even if at the time of insert those fields [updatedAt, createdAt] are empty or not part of the input struct, the result will return whatever that is there in database. If the createdAt or updatedAt are created by postgres and nonEmpty it will be returned.
update :- We can use default values
type HasUuidPkey struct {
ID uuid.UUID `gorm:"primaryKey;default:gen_random_uuid()"`
Name string
CreatedAt time.Time
}
Playground example
I currently have a Club and Tag table and I wanted to obtain all of the clubs that have at least 1 of those given tags.
type Club struct {
ID uint
Sets []Tag `gorm:"many2many:club_tag;foreignKey:id;References:name"
}
type Tag struct {
ID uint
Name string
}
I made this query which ends up returning the clubs that have that particular tag most of the time however, sometimes I encounter these issues.
var clubs []Club
var tags []string
db.Joins("JOIN club_tag ON club_tag.club_id=club.id).
Joins("JOIN tag ON club_tag.tag_name=tag.name").
Where("tag.name IN ?", tags).
Find(&clubs)
> ERROR: column club_tag.deleted_at does not exist (SQLSTATE 42703)
> Error: missing FROM-clause entry for table "club_tag" (SQLSTATE 42P01)
Am I missing something in this query such that it won't return an error?
I'm currently using GORM v2 and tried to follow this example
Any help is appreciated! Thanks :)
based on your errors :
ERROR: column club_tag.deleted_at does not exist (SQLSTATE 42703)
Error: missing FROM-clause entry for table "club_tag" (SQLSTATE 42P01)
Your first error says you club_tag hasn't deleted_at, I think your struct has gorm.Model data. from documentation of gorm v2:
GORM defined a gorm.Model struct, which includes fields ID, CreatedAt, UpdatedAt, DeletedAt
when you create query for struct which has gorm.Model. gorm in default created deleated_at = null on query. so I think you should remove gorm.Model and create what fields you want.
Your second error says your query hasn't any table on join. so I think you must check your table names.
I have a table orders with a field order_detail of type hstore which saves json data.
Now I want to query on the inner objects of my json data. because The query is somehow complicated I'm trying to tell my problem in easier scenario.
I have tested these 4 subqueries:
Get the original saved json:
select order_detail::json as original
from orders;
This query successfully returns the json formatted data.
Get the inner object 'transaction' inside the order_details:
select order_detail::json as original,
(order_detail -> 'transaction')::json as transaction
from order_details;
This query also works successfully.
Get the id of that transaction:
select order_detail::json as original,
(order_detail -> 'transaction')::json as transaction,
((order_detail -> 'transaction')::json -> 'id')::text as id
from order_details;
The above also works successfully and returns the original json, transaction and id inside the transaction.
Select based on the result of query 3 and get one of the results:
select original
from
(select order_detail::json as original,
(order_detail -> 'transaction')::json as transaction,
((order_detail -> 'transaction')::json -> 'id')::text as id
from order_details) s
where transaction is null and id is null;
This query will raise an exception! The exception says that:
[22P02] ERROR there is a token '=' is invalid**
Why does this exception occurs only in the 4th query? Can anyone help me on this?
Finally I found the problem. When you want have such a field which is json stored in hstore, if you use a simple query you can use something like this:
order_detail -> 'trasaction'
and this will return the transaction part of hashed-stored data in the order_detail field with no problem.
BUT if you want to use such thing in a nested query, you MUST explicitly declare that the field is json. so you must use something like this instead (in all parts of inner query):
order_detail::json -> 'transaction'
I have some tables that represent various types. They usually just consist of an ID (int), and a name. Ideally I would have this in an enum. Is there a way to map a table like this onto an enum?
EDIT: How would I handle it if there were extra fields other than an ID and Name?
If it's just an id and a name, I generally do this:
public enum FootScent : int
{
Unknown = 0,
Mild = 1,
Sweaty =2,
SteppedInSomething = 3
}
and then on the LINQ entity property:
[Column("foot_scent_id", DbType = "Int NOT NULL")]
public FootScent Scent { get; set; }
For lookup tables with columns other than "id" and "name" that are needed, I usually just make a normal LINQ entity for them, though depending on your implementation it would probably be worth caching these to minimize trips to the DB.