【问题标题】:sort_by multiple attributes in hashsort_by 哈希中的多个属性
【发布时间】:2020-08-18 00:09:01
【问题描述】:

我希望能够对我的帖子进行排序

  • created_at asc(包括距离)
  • vote_count desc(包括距离)
  • 距离上升

到目前为止,我已经能够按距离排序,但我无法弄清楚如何构建我的地图,并且仍然能够让数组中的用户看到distance(即使他们选择了例如,按vote_count 排序)

用户从视图中调用 update_order

def update_order
  @order = params[:order]
  @posts = Post.all
  get_distance_posts
end

确定距离的方法:

def get_distance_posts
    posts = {}
    @posts.map{ |post| posts[post.id] = (check_coordinates_present?(post, current_user) ? get_users_distance(post,current_user) : 0 ) }
    @sorted_posts = Hash[*posts.sort_by {|_key, value| value}.flatten]
end

我的 view.html.erb

<% @sorted_posts.map do |u_id, dist|  %>
    <% post = @posts.find(u_id) %>
    <p> <%= post.created_at %> </p>
    <p> <%= post.vote_count %> </p>
    <p><%= dist %></p>
<% end%>

任何帮助将不胜感激!

【问题讨论】:

  • 我不明白这个问题。每个帖子都是哈希吗?它是如何失去领域的?
  • “丢失字段”是什么意思?我在帮助程序中计算帖子和 current_user 之间的实时距离,然后通过将帖子转换为哈希将帖子和用户之间的距离映射到帖子对象。澄清一下:我已经弄清楚如何按距离对哈希进行排序——但是我如何按其他方式对@sorted_posts 进行排序,并且仍然包括距离编号而不按距离排序?
  • 我怀疑你想要像obj.sort_by { |e| [e.created_at, -e.vote_count, e.distance] } 这样的东西。数组与方法Array#<=> 进行比较。尤其参见文档的第三段。
  • 只是指出,在标准时间戳实现中,created_at 是一个日期时间对象,它存储对象的创建时间直到秒。按created_at 排序,然后按任何其他字段排序与仅按created_at 排序相同,因为您不太可能有两条具有相同created_at 值的记录。

标签: ruby-on-rails ruby ruby-on-rails-6 geocoder


【解决方案1】:

首先,您不应该在 Ruby 中进行排序。您将从数据库中提取所有记录,并且您的服务器将开始出现严重的性能问题,并最终在您的应用扩展时开始崩溃,因为它会耗尽可用内存。

相反,您想使用 .order 向查询添加一个 order 子句来对结果进行排序。

Post.near([48.848903, 2.354533])
    .order(
       created_at: :asc, 
       vote_count: :desc
    )

这允许您对查询应用分页和限制,以防止上述内存问题。

.near 是由Geocoder gem 提供的特殊范围,它选择两个特殊计算的地理空间列-distancebearing。它还按距离排序。

这里我使用的是一组静态坐标,但您可以从您的模型中传递一组坐标,甚至是一个将被地理编码的地址:

# to_coordinates is provided by Geocoder
Post.near(user.to_coordinates)
    .order(
       created_at: :asc, 
       vote_count: :desc
    )
Post.near("Beijing")
    .order(
       created_at: :asc, 
       vote_count: :desc
    )

如果您想选择距离但不将其用于排序,请使用 .reorder 替换查询的 order 子句:

Post.near(user.to_coordinates)
    .reorder(
       created_at: :asc, 
       vote_count: :desc
    )

【讨论】:

  • 如果您使用的是 postgres,您可以使用 PostGIS 扩展进一步优化这一点,该扩展使用专门的地理空间列类型提供更有效(和精确)的距离计算。
  • 一句警告;这里的社区喜欢将简单的 Ruby 解决方案用于真正应该在 RDBMS 中解决的问题,因为用创造性循环或设计模式来解决问题“更有趣”。这并不一定意味着这是个好主意。
  • 这很棒。非常感谢。
【解决方案2】:

选项 1:使用presenter object。为每个帖子创建一个演示者,让演示者计算距离并将其存储在自身中,对演示者而不是帖子进行排序,渲染演示者。

选项 2:在地图中存储从帖子 ID 到距离的距离。在渲染帖子时,在帖子id-距离图中查找对应的距离。

【讨论】:

    猜你喜欢
    • 2021-04-25
    • 2018-03-09
    • 1970-01-01
    • 2020-06-17
    • 2017-04-24
    • 1970-01-01
    • 2012-02-27
    • 2021-01-22
    • 1970-01-01
    相关资源
    最近更新 更多