tianyuan-api-server/apps/sentinel/internal/model/userproductsmodel.go

140 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package model
import (
"context"
"database/sql"
"fmt"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
)
var _ UserProductsModel = (*customUserProductsModel)(nil)
type UserProductItem struct {
Id int64 `db:"id"`
UserId int64 `db:"user_id"`
ProductId int64 `db:"product_id"`
ProductName string `db:"product_name"`
ProductCode string `db:"product_code"`
ProductDescription sql.NullString `db:"product_description"`
ProductGroup string `db:"product_group"`
ProductPrice float64 `db:"product_price"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
type (
// UserProductsModel is an interface to be customized, add more methods here,
// and implement the added methods in customUserProductsModel.
UserProductsModel interface {
userProductsModel
FindUserProductsList(ctx context.Context, userId, page, pageSize int64) ([]*UserProductItem, int64, error)
FindOneUserProduct(ctx context.Context, userId, productId int64) (*UserProducts, error)
FindMatchUserProductCode(ctx context.Context, userId int64, productCode string) (bool, error)
}
customUserProductsModel struct {
*defaultUserProductsModel
rds *redis.Redis
}
)
// NewUserProductsModel returns a model for the database table.
func NewUserProductsModel(rds *redis.Redis, conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) UserProductsModel {
return &customUserProductsModel{
rds: rds,
defaultUserProductsModel: newUserProductsModel(conn, c, opts...),
}
}
func (m *defaultUserProductsModel) FindUserProductsList(ctx context.Context, userId, page, pageSize int64) ([]*UserProductItem, int64, error) {
offset := (page - 1) * pageSize
var userProducts []*UserProductItem
// SQL查询语句手动选择需要的products字段
query := `
SELECT
up.id AS user_product_id,
up.user_id,
p.id AS product_id,
p.product_name,
p.product_code,
COALESCE(p.product_description, '') AS product_description,
p.product_group,
up.product_price,
up.created_at,
up.updated_at
FROM user_products up
JOIN products p ON up.product_id = p.id
WHERE up.user_id = ?
ORDER BY up.created_at DESC
LIMIT ?, ?`
// 执行查询
err := m.QueryRowsNoCacheCtx(ctx, &userProducts, query, userId, offset, pageSize)
if err != nil {
return nil, 0, err
}
// 查询总数量
var total int64
countQuery := "SELECT COUNT(*) FROM user_products WHERE user_id = ?"
err = m.QueryRowNoCacheCtx(ctx, &total, countQuery, userId)
if err != nil {
return nil, 0, err
}
return userProducts, total, nil
}
func (m *customUserProductsModel) FindOneUserProduct(ctx context.Context, userId, productId int64) (*UserProducts, error) {
var userProduct UserProducts
query := fmt.Sprintf("SELECT %s FROM %s WHERE `user_id` = ? AND `product_id` = ? LIMIT 1", userProductsRows, m.table)
err := m.QueryRowNoCacheCtx(ctx, &userProduct, query, userId, productId)
switch err {
case nil:
return &userProduct, nil
case sqlc.ErrNotFound:
// 返回未找到的错误
return nil, ErrNotFound
default:
// 其他错误
return nil, err
}
}
func (m *customUserProductsModel) FindMatchUserProductCode(ctx context.Context, userId int64, productCode string) (bool, error) {
// 定义 Redis 缓存 Set 键
redisKey := fmt.Sprintf("user_products:%d", userId)
// 1. 检查 Redis Set 中是否存在用户与产品的关联
isMember, err := m.rds.SismemberCtx(ctx, redisKey, productCode)
if err == nil && isMember {
// 如果 Redis Set 中存在,表示关联已存在,返回 true
return true, nil
}
// 2. 如果 Redis 中没有匹配,则查询数据库
query := `
SELECT COUNT(*)
FROM user_products up
JOIN products p ON up.product_id = p.id
WHERE up.user_id = ? AND p.product_code = ?`
var count int
err = m.QueryRowNoCacheCtx(ctx, &count, query, userId, productCode)
if err != nil {
// 如果数据库查询出错,返回错误
return false, err
}
// 3. 如果数据库查询成功且有记录,更新 Redis Set 并返回 true
if count > 0 {
_, redisErr := m.rds.SaddCtx(ctx, redisKey, productCode)
if redisErr != nil {
return false, redisErr // Redis 更新失败
}
return true, nil
}
// 4. 如果没有找到匹配的关联,返回 false
return false, nil
}