Conversation
| CREATE TABLE category | ||
| ( | ||
| id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY, | ||
| name text NOT NULL UNIQUE | ||
| ); | ||
|
|
There was a problem hiding this comment.
Новые изменения в схеме должны описываться в отдельной миграции, т.к. на проде вы не пересоздаете базу, а делаете изменения над существующей схемой.
There was a problem hiding this comment.
Также нужно учитывать, что база находится под нагрузкой, т.е. тяжелые операции требующие блокировки таблицы нельзя использовать. Также нужно учитывать как изменения в схеме согласуются с кодом бекенда, например если нужно изменить имя колонки, то в таком случае стоит сделать две миграции и один релиз с бекендом - в первой миграции добавляйте колонку с новым именем, затем выкатывайте релиз в котором в запросах обращайтесь к новой колонке, затем во второй миграции дропайте старую колонку.
There was a problem hiding this comment.
миграции поправим уже отдельным пр, ок?
| country_id integer REFERENCES country (id), | ||
| UNIQUE (name, city_id) | ||
| UNIQUE (name, city_id), | ||
| category_id integer REFERENCES category (id) |
There was a problem hiding this comment.
Тут тоже самое - нужна инструкция ALTER TABLE и скрипт установки значений категории.
There was a problem hiding this comment.
Если сейчас нет времени править - оставляйте как есть.
| @@ -28,10 +29,19 @@ func (ss *SightStorage) GetSightsList() ([]entities.Sight, error) { | |||
| var sights []*entities.Sight | |||
| ctx := context.Background() | |||
There was a problem hiding this comment.
Контекст нужно прокидывать снаружи, чтобы иметь возможность отменить операцию и освободить коннтект к базе
|
|
||
| err := pgxscan.Select(ctx, ss.db, &sight, `SELECT sight.id, COALESCE(rating, 0) AS rating, sight.name, description, city_id, sight.country_id, im.path, city.city, country.country | ||
| FROM sight | ||
| INNER JOIN image_data AS im | ||
| ON sight.id = im.sight_id | ||
| INNER JOIN city | ||
| ON sight.city_id = city.id | ||
| INNER JOIN country | ||
| ON sight.country_id = country.id | ||
| WHERE sight.id = $1`, id) | ||
| err := pgxscan.Select(ctx, ss.db, &sight, | ||
| `SELECT sight.id, | ||
| COALESCE(rating, 0) AS rating, | ||
| sight.name, | ||
| description, | ||
| city_id, | ||
| sight.country_id, | ||
| im.path, | ||
| city.city, | ||
| country.country, | ||
| category_id, | ||
| category.name AS category | ||
| FROM sight | ||
| INNER JOIN image_data AS im | ||
| ON sight.id = im.sight_id | ||
| INNER JOIN city | ||
| ON sight.city_id = city.id | ||
| INNER JOIN country | ||
| ON sight.country_id = country.id | ||
| INNER JOIN category | ||
| ON sight.category_id = category.id | ||
| WHERE sight.id = $1`, id) | ||
| if err != nil { | ||
| return entities.Sight{}, err | ||
| } | ||
|
|
||
| return *sight[0], nil |
There was a problem hiding this comment.
Для чтения одной строки стоит использовать pgxscan.Get
| first = false | ||
| } | ||
| if key == "rating" || key == "city_id" || key == "country_id" || key == "category_id" { | ||
| query.WriteString(fmt.Sprintf("%s = %s", key, value)) |
There was a problem hiding this comment.
Нужно все аргументы передавать через плейсхолдеры. Такое простроение запросов позволяет атаковать бек через sql инъекции.
There was a problem hiding this comment.
Для построения "сложных" запросов можно использовать пакеты squirrel или xorm/builder
| rows, err := ss.db.Query(context.Background(), query, "%"+str+"%") | ||
| if err != nil { | ||
| return entities.Sights{}, err | ||
| func (ss *SightStorage) SearchSights(searchParams map[string]string) (entities.Sights, error) { |
There was a problem hiding this comment.
Параметры запроса нужно сделать обычными переменными с указанием типа
There was a problem hiding this comment.
то есть не мапой? а если у нас в будущем планируется поиск не только по имени, но и по стране, городу и тд? все 11 параметров передавать отдельно?
There was a problem hiding this comment.
Да, отдельно или в структуре
| var sightList []entities.Sight | ||
| for _, s := range sights { | ||
| sightList = append(sightList, *s) | ||
| } |
There was a problem hiding this comment.
Можно сразу сканировать в []entities.Sight
utils/httputils/httputils.go
Outdated
| } | ||
|
|
||
| func SetQueryParamToCtx(ctx context.Context, queryParams map[string]string) context.Context { | ||
| return context.WithValue(ctx, RequestQueryParamsKey, queryParams) |
There was a problem hiding this comment.
Вроде в ранних PRах обсуждали, что лучше в качестве ключа использовать собственный тип, а не строку. Это необходимо делать чтобы избежать коллизий.
в ручку получения списка достопримечательностей добавлена возможность передачи query параметра category_id