I have a react app that fetches data from golang api which queries data from postgres database. One of my models is deeply nested JSON so I used JSONB datatype in postgres.
CREATE table rules (
id serial primary key,
rule jsonb
);
In golang, I have the structure
type Rule struct {
ID int `json:"id"`
Name string `json:"name"`
...succeeding fields are deeply nested data
}
And in the SPA I have the model
interface Rule {
id number
name string
....same as from the golang api model
}
To create a new Rule
object in the SPA, I assign 0
to id
. The newly created rule is sent to golang rest api. Then in the api, I first ask the postgres database for the next value for the serial id (using POSTGRES nextval
), assign that acquired id into the Rule struct ID field,
nextValidId := <result of nextval>
rule.ID = nextValidId
JSON marshal the rule object then insert to db
ruleBytes, _ := json.Marshal(rule)
INSERT INTO rules_table VALUES (<nextValidId>, <ruleBytes>);
This way I avoided duplicate ids which may happen if an SPA is handling the Id generation. However, I find my method somewhat complicated already. I know I can generate ids from SPA too but how do I avoid duplicated ids without using the method I used above? or am I overthinking things?
Update1: I also thought about adding another Rule struct in golang without the ID
field so that I don't have to use nextval
just to put the id inside the JSON, but is it a good programming design to have multiple models for inserting and retrieving from db and another model for response to the SPA?
Let the database generate the new id since that's exactly SERIAL
types are for in PostgreSQL.
In golang, you can insert a new record and retrieve the generated id by using sql.DB.QueryRow(...)
and .Scan()
using an insert statement with a RETURNING
clause, e.g.:
var newId int
query := "INSERT INTO rules (rule) VALUES ($1) RETURNING id"
err := db.QueryRow(query, newRule).Scan(&newId)
// TODO: check err
log.Printf("newId=%d", newId)