search nickname

pull/3727/head
hawklin2017 2 months ago
parent d787d49d48
commit 48e023882a

@ -165,6 +165,8 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
userRouterGroup.POST("/set_msg_receive_setting", u.SetMsgReceiveSetting)
// 根据手机号精确查找用户phoneSearchVisibility=true 时遵守 phone_visibility 设置)
userRouterGroup.POST("/get_user_by_phone", u.GetUserByPhone)
// 根据昵称精确查询用户(可多结果,与 getPaginationUsers 模糊搜索不同)
userRouterGroup.POST("/get_users_by_nickname", u.GetUsersByNickname)
// 全局黑名单管理(仅管理员)
userRouterGroup.POST("/add_global_blacklist", bl.AddGlobalBlacklist)

@ -321,3 +321,7 @@ func (u *UserApi) SetMsgReceiveSetting(c *gin.Context) {
func (u *UserApi) GetUserByPhone(c *gin.Context) {
a2r.Call(c, user.UserClient.GetUserByPhone, u.Client)
}
func (u *UserApi) GetUsersByNickname(c *gin.Context) {
a2r.Call(c, user.UserClient.GetUsersByNickname, u.Client)
}

@ -22,6 +22,7 @@ import (
"strings"
"sync"
"time"
"unicode/utf8"
"github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
@ -451,6 +452,61 @@ func (s *userServer) GetUserByPhone(ctx context.Context, req *pbuser.GetUserByPh
return &pbuser.GetUserByPhoneResp{UserInfo: pbUser}, nil
}
// GetUsersByNickname 按昵称精确匹配查询普通用户app_manger_level 与分页拉取用户一致)。
// 全局黑名单用户会被过滤;手机号字段按 phone_visibility 与 getDesignateUsers 相同规则处理。
func (s *userServer) GetUsersByNickname(ctx context.Context, req *pbuser.GetUsersByNicknameReq) (*pbuser.GetUsersByNicknameResp, error) {
nickname := strings.TrimSpace(req.Nickname)
if nickname == "" {
return nil, errs.ErrArgs.WrapMsg("nickname is required")
}
if n := utf8.RuneCountInString(nickname); n < 1 || n > 64 {
return nil, errs.ErrArgs.WrapMsg("nickname length must be 1-64 characters")
}
users, err := s.db.FindOrdinaryUsersByNickname(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, nickname)
if err != nil {
log.ZError(ctx, "GetUsersByNickname: FindOrdinaryUsersByNickname failed", err,
"opUserID", mcontext.GetOpUserID(ctx), "nickname", nickname)
return nil, err
}
if len(users) == 0 {
return &pbuser.GetUsersByNicknameResp{}, nil
}
userIDs := datautil.Slice(users, func(u *tablerelation.User) string { return u.UserID })
blocked, err := s.globalBlackDB.FindBlocked(ctx, userIDs)
if err != nil {
log.ZError(ctx, "GetUsersByNickname: FindBlocked failed", err,
"opUserID", mcontext.GetOpUserID(ctx), "count", len(userIDs))
return nil, err
}
if len(blocked) > 0 {
banned := make(map[string]struct{}, len(blocked))
for _, b := range blocked {
banned[b.UserID] = struct{}{}
}
filtered := make([]*tablerelation.User, 0, len(users))
for _, u := range users {
if _, ok := banned[u.UserID]; !ok {
filtered = append(filtered, u)
}
}
users = filtered
}
if len(users) == 0 {
return &pbuser.GetUsersByNicknameResp{}, nil
}
pbUsers := convert.UsersDB2Pb(users)
viewerID := mcontext.GetOpUserID(ctx)
if err := s.applyPhoneVisibility(ctx, viewerID, pbUsers, users); err != nil {
log.ZError(ctx, "GetUsersByNickname: applyPhoneVisibility failed", err,
"opUserID", viewerID, "count", len(users))
return nil, err
}
return &pbuser.GetUsersByNicknameResp{UsersInfo: pbUsers}, nil
}
func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckReq) (resp *pbuser.AccountCheckResp, err error) {
resp = &pbuser.AccountCheckResp{}
if datautil.Duplicate(req.CheckUserIDs) {

@ -37,6 +37,8 @@ type UserDatabase interface {
Find(ctx context.Context, userIDs []string) (users []*model.User, err error)
// Find userInfo By Nickname
FindByNickname(ctx context.Context, nickname string) (users []*model.User, err error)
// FindOrdinaryUsersByNickname 昵称精确匹配,仅普通用户(与分页拉取用户 level 一致)
FindOrdinaryUsersByNickname(ctx context.Context, level1 int64, level2 int64, nickname string) (users []*model.User, err error)
// FindByPhone looks up a single user by exact phone number.
// Returns errs.ErrRecordNotFound if no user has the given phone.
FindByPhone(ctx context.Context, phone string) (user *model.User, err error)
@ -138,6 +140,10 @@ func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (use
return u.userDB.TakeByNickname(ctx, nickname)
}
func (u *userDatabase) FindOrdinaryUsersByNickname(ctx context.Context, level1, level2 int64, nickname string) ([]*model.User, error) {
return u.userDB.FindOrdinaryUsersByNickname(ctx, level1, level2, nickname)
}
func (u *userDatabase) FindByPhone(ctx context.Context, phone string) (*model.User, error) {
return u.userDB.FindByPhone(ctx, phone)
}

@ -38,10 +38,12 @@ func NewUserMongo(db *mongo.Database) (database.User, error) {
Options: options.Index().SetUnique(true),
},
{
// 支持按手机号快速查找phone 为空串的文档不参与索引
Keys: bson.D{{Key: "phone", Value: 1}},
Options: options.Index().SetSparse(true),
},
{
Keys: bson.D{{Key: "nickname", Value: 1}},
},
}
if _, err := coll.Indexes().CreateMany(context.Background(), indexes); err != nil {
return nil, errs.Wrap(err)
@ -80,6 +82,14 @@ func (u *UserMgo) TakeByNickname(ctx context.Context, nickname string) (user []*
return mongoutil.Find[*model.User](ctx, u.coll, bson.M{"nickname": nickname})
}
func (u *UserMgo) FindOrdinaryUsersByNickname(ctx context.Context, level1, level2 int64, nickname string) ([]*model.User, error) {
query := bson.M{
"nickname": nickname,
"app_manger_level": bson.M{"$in": []int64{level1, level2}},
}
return mongoutil.Find[*model.User](ctx, u.coll, query, options.Find().SetLimit(100))
}
func (u *UserMgo) FindByPhone(ctx context.Context, phone string) (*model.User, error) {
return mongoutil.FindOne[*model.User](ctx, u.coll, bson.M{"phone": phone})
}

@ -29,6 +29,8 @@ type User interface {
Take(ctx context.Context, userID string) (user *model.User, err error)
TakeNotification(ctx context.Context, level int64) (user []*model.User, err error)
TakeByNickname(ctx context.Context, nickname string) (user []*model.User, err error)
// FindOrdinaryUsersByNickname 按昵称精确匹配,且 app_manger_level 为普通用户范围(与分页拉取用户一致)
FindOrdinaryUsersByNickname(ctx context.Context, level1 int64, level2 int64, nickname string) (users []*model.User, err error)
FindByPhone(ctx context.Context, phone string) (user *model.User, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*model.User, err error)
PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*model.User, err error)

Loading…
Cancel
Save