Gorm Join table query - sql

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.

Related

PostgreSQL type cast not working when using with UPDATE statement

I have a column address in students table which actually stores a JSON object but it is of type text for legacy reasons. Now, to get the value of any of these keys in the json object, I use postgres type cast :: operator with json -> operator as shown
select address::jsonb->'pincode' from students where id='xyz';
This query returns the correct pincode for the student with id xyz. Now lets say, I want to update the pincode for a student, and now, if I do something like
update students set address::jsonb->'pincode'='182741' where id='abc';
I get this error
ERROR: syntax error at or near "::"
I know I can overwrite the entire column value but that is a lot to do if you just want to update one key. Can anyone help me understand why we cannot use the type cast operator here? Any what is the correct way to update only one key in the JSON object?
Use jsonb_set from here JSON functions.
create table students (id integer, address varchar);
insert into students values (1, '{"name": "Adrian", "pincode": 1234}');
select address::jsonb->'pincode' from students where id=1;
1234
update students set address = jsonb_set(address::jsonb, '{pincode}', '182741') where id =1;
select * from students;
id | address
----+---------------------------------------
1 | {"name": "Adrian", "pincode": 182741}

Sort records with an associated field

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

How do i list all entries where a specific value in a column does not exist?

Basically, I have a table called Client Entity that contains an Entity Type column and I have an entity type called BEN. I want to show all records where this particular type does not exist. The issue is that the record itself may not exist if the entity type has not been appointed so I am basically asking the query to show me where no 'rows' exists because of this value...
Basically I'm looking for a code to highlight the absence of data, not NULL values.
Can anyone help ?
If you have a table of "records", then you would use not exists:
select r.*
from records r
where not exists (select 1
from cliententity ce
where ce.record_id = r.record_id and
ce.entity_type = 'BEN'
);
I don't know what your real table or column names are, but this gives the idea on how to approach the problem.

Parameterization of an array of enums?

I have a table where one of the fields is an array of enums. For example let say this is what it looks like:
CREATE TYPE foobar AS ENUM (
'FOO',
'BAR'
);
CREATE TABLE my_table (
id SERIAL PRIMARY KEY,
foobarray foobar[] DEFAULT ARRAY['FOO']::foobar[]
);
When I try to use node-postgres to insert/update a row it is not clear how to parameterize the array and get it type cast to an array of enums.
When I try:
const foobarray = ["BAR"];
await pool.query("UPDATE my_table SET foobarray=$2::foobar[] WHERE id=$1", [id, foobarray]);
I get:
error: invalid input value for enum foobarray: "{"
Any ideas how to get this to work?
I figured out my issue...
I was actually pulling the value, before updating it, as follows:
SELECT foobarray FROM my_table WHERE id=$1;
This resulted in the following array being in the result:
["{", "}", "FOO"]
I didn't realize this and was trying to modify the array from the result before updating which resulted in "{" and "}" which are obviously not valid ENUM values being passed through.
I was able to solve this issue by keeping my original UPDATE query the same but modifying the SELECT query to:
SELECT foobarray::text[] FROM my_table WHERE id=$1;
This results in the following array being in the result:
["FOO"]
Tweaking it and updating now causes no problems.

Fetching records which have either of two values in an array column in postgres

I have an array_agg column in postgresql which has values like these:
"{Metabolic/Endocrinology}"
"{Cardiovascular}"
"{Oncology}"
"{Autoimmune/Inflammation}"
Basically a string variable being array_agg by an id.
Now I want to fetch all records from this table where either of Oncology or Autoimmune/Inflammation is present.
I am doing something like this but I am not sure why it is throwing an error.
select * from Table where id = ANY('{Oncology,Autoimmune/Inflammation}')
It throws the following error.
ERROR: operator does not exist: text[] = text
SQL state: 42883
Hint: No operator matches the given name and argument type(s). You may need to add explicit type casts.
Character: 67
Please note I have also used ::TEXT [] and it still gives an error.
You want to use the array-overlaps operator &&.
See array operators.
e.g.
select * from (
VALUES
(ARRAY['Oncology','Pediatrics']),
(ARRAY['Autoimmune/Inflammation','Oncology']),
(ARRAY['Autoimmune/Inflammation']),
(ARRAY['Pediatrics']),
(ARRAY[]::text[])
) "Table"(id)
where id && ARRAY['Oncology','Autoimmune/Inflammation'];
By the way, I suggest using the SQL-standard ARRAY[...] constructor where possible.
Also, it's almost certainly a terrible idea to have an id column (presumably a primary key, if not, the name is confusing) defined as an array type.