【发布时间】:2021-05-08 22:14:03
【问题描述】:
我正在做一个项目,我必须在其中展示组。
涉及以下模型
组
class Group < ApplicationRecord
has_many :user_groups, dependent: :destroy
has_many :users, through: :user_groups
belongs_to :creator, :class_name => "User", :foreign_key => "creator_id"
belongs_to :group_status
has_many :matches, dependent: :destroy
has_many :liked, :through => :matches, :source => :macther
has_many :inverse_matches , :class_name => "Match" , :foreign_key => "matcher_id", dependent: :destroy
has_many :liked_by, :through => :inverse_matches, :source => :group
enum status: %w[active inactive]
reverse_geocoded_by :latitude, :longitude
end
用户
class User < ApplicationRecord
has_one :setting, dependent: :destroy
has_many :friendships, dependent: :destroy #, :class_name => "Friendship", :foreign_key => 'user_id'
has_many :invited, :through => :friendships, :source => :friend
has_many :inverse_friendships , :class_name => "Friendship" , :foreign_key => "friend_id", dependent: :destroy
has_many :invited_by, :through => :inverse_friendships, :source => :user
has_many :user_groups, dependent: :destroy
has_many :groups, through: :user_groups
has_many :group_creations, :foreign_key => :creator_id, :class_name => 'Group'
has_many :group_statuses
has_many :matches, dependent: :destroy
enum gender: %w[male female other]
end
用户组
class UserGroup < ApplicationRecord
belongs_to :user
belongs_to :group
enum status: %w[pending joined reported]
attr_accessor :invite_id
end
匹配
class Match < ApplicationRecord
belongs_to :group
belongs_to :matcher, :class_name => "Group"
belongs_to :user
enum status: %w[like match unlike block blocked report reported]
end
首先根据用户的年龄、性别和组员人数等偏好显示组,然后显示其余用户。
我所做的是首先排除所有不符合用户偏好的组并显示剩余的组,而不是显示那些不符合用户偏好的组。
这就是算法的样子
1- 查找与群组成员计数不匹配的群组
group_member_count_check = Group.joins(:users).joined_group.group('groups.id')
.having("count(groups.id) != #{setting.group_member_count}").pluck(:id)
2- 查找不符合性别偏好的组
if setting.male_only
gender_check = Group.joins(:users).joined_group.where('users.gender !=?', 0).pluck(:id)
elsif setting.female_only
gender_check = Group.joins(:users).joined_group.where('users.gender !=?', 1).pluck(:id)
end
3- 比删除当前用户包含被阻止用户的组
blocked_users = current_user.friendships.where(friendships: {status: 2}).pluck(:friend_id) +
current_user.inverse_friendships.where(friendships: {status: 2}).pluck(:user_id)
blocked_group_ids = Group.joins(:users).joined_group.where(users: {id: blocked_users}).pluck(:id)
4- 删除已经喜欢/不喜欢的组
already_liked_or_matched_id = (group.matches.where(status: [0,1,3,4,5,6]).pluck(:matcher_id)
+ current_user.matches.where(status: [2]).pluck(:matcher_id)).uniq
现在首先返回不包括上述提取组的组
groups = Group.includes(:group_status, :users)
.where(status: 'active', spot_light_enabled: false)
.where.not(id: group_member_count_check + gender_check +blocked_group_ids + already_liked_or_matched_id )
.near([latitude, longitude], setting.max_distace, order: 'random()').page(params[:page]).per(params[:per_page])
如果没有首选组,则显示其他组
if groups.length.zero?
groups = Group.includes(:group_status, :users).where(status: 'active')
.where(id: gender_check + group_member_count_check)
.where.not(id: blocked_group_ids + already_liked_or_matched_id )
.near([latitude, longitude], 10000, order: 'random()').page(params[:page]).per(params[:per_page])
end
回复是这样的
{
groups: groups,
pagination: pagination_dict(Group.where.not(id: blocked_group_ids ).page(params[:page]).per(params[:per_page]))
}
架构
create_table "users", id: :serial, force: :cascade do |t|
t.string "phone_number"
t.string "user_name"
t.string "authentication_token"
t.string "first_name"
t.string "last_name"
t.text "bio"
t.date "dob"
t.integer "age"
t.integer "gender"
t.integer "group_id"
t.decimal "latitude", precision: 15, scale: 6
t.decimal "longitude", precision: 15, scale: 6
t.string "city"
t.string "state"
t.boolean "creator", default: false
t.boolean "is_premium", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "instant_match_allow", default: 1
t.integer "spot_light_allow", default: 1
t.boolean "is_blocked", default: false
t.boolean "is_new", default: true
t.index ["authentication_token"], name: "index_users_on_authentication_token"
t.index ["phone_number"], name: "index_users_on_phone_number", unique: true
t.index ["user_name"], name: "index_users_on_user_name", unique: true
end
create_table "groups", force: :cascade do |t|
t.integer "group_status_id"
t.string "name"
t.integer "status", default: 0
t.decimal "latitude", precision: 15, scale: 6
t.decimal "longitude", precision: 15, scale: 6
t.string "city"
t.string "state"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "creator_id"
t.integer "instant_match_allow", default: 1
t.integer "spot_light_allow", default: 1
t.boolean "spot_light_enabled", default: false
t.datetime "spot_light_time"
t.integer "place_id"
t.index ["group_status_id"], name: "index_groups_on_group_status_id"
end
create_table "user_groups", force: :cascade do |t|
t.integer "user_id"
t.integer "group_id"
t.boolean "creator", default: false
t.integer "status", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "matches", force: :cascade do |t|
t.integer "group_id"
t.integer "matcher_id"
t.integer "status"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "chat_id"
end
现在的问题
1- 主要是查询太多(我必须进行更多检查但排除已显示的组等)
2- 分页没有按预期工作(由于从首选组切换到其他组而跳过一些页面)
管理此问题的首选方法是什么?
【问题讨论】:
-
嘿——是否可以看到
groups和user_groups以及user_groups模型的架构?我怀疑很多这些连接是不必要的,但这只是猜测,直到我在架构的完整上下文中 -
@DamilareOlusakin 更新了模型关系和模式的问题