Ruby on Rails optimal search with array of filter values?

回眸只為那壹抹淺笑 提交于 2019-12-11 13:41:01

问题


I have a specific example, but the general question is: whats the optimal way to retrieve records when you have an array of filter values to match?

Say I have User and Post records where User has_many :posts

and I have a Relationship model that looks like this:

class Relationship < ActiveRecord::Base
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
  validates :follower_id, presence: true
  validates :followed_id, presence: true
end

I want to write a function that returns chronologically ordered posts from your followings' following - that is, all the posts from users that the users you follow are following, excluding duplicates and posts from anyone you follow.

My solution is to first compile an array of all the users of interest:

users = []
@user.following.each do |f|
  f.following.each do |ff|
    users << ff
  end
end

# dedupe
users = users.uniq

#remove self and following
users.delete(@user)
@user.following.each do |f|
  users.delete(f)
end

then compile their posts and order them:

posts = []
users.each do |u|
  posts += u.posts
end
posts.sort_by!{|x| x[:created_at]}.reverse!

I think there's a better way to do this with Active Record functions, but I can't figure out how to make them work with an array. For instance, if I compile an array of User id values instead of the full models, and try to run this code to get the post array:

posts = Post.where(
  user_id: user_ids
).order('created_at DESC').limit(21)

it returns an empty array. Is there a better way to search with an array of filter values than my current solution?

Update: additional modal code:

class Post < ActiveRecord::Base
  belongs_to :user
  ...

User.rb

class User < ActiveRecord::Base
  has_many :photos
  has_many :active_relationships, class_name:  "Relationship",
                              foreign_key: "follower_id",
                              dependent:   :destroy
  has_many :passive_relationships, class_name:  "Relationship",
                               foreign_key: "followed_id",
                               dependent:   :destroy
  has_many :following, through: :active_relationships, source: :followed
  has_many :followers, through: :passive_relationships, source: :follower
  ...

回答1:


Your idea of using user_ids is a good one. If that query returned an empty array, then did you check to make sure that the user_ids were the ones that you expected?

As for the code, you need to look into Enumerable#map and #flat_map. They are built-in ruby methods to accomplish what you're trying to do with the #each loops. Your code might reduce to something like:

user_ids = user.followings.flat_map { |following| following.following_id }
user_ids.uniq!
user_ids -= [user.id, user.following_ids].flatten
Post.where(user_id: user_ids).order(id: :desc).limit(21)

Note: Since created_at should follow id creation order, I would consider searching based on id rather than created_at since it should have an index.



来源:https://stackoverflow.com/questions/36344662/ruby-on-rails-optimal-search-with-array-of-filter-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!