简体   繁体   English

使用join和group by时,rails中的will_paginate

[英]will_paginate in rails when using join and group by

I noticed that when using will_paginate 20 results a page, joining multiple tables group_by "nickname", the output is paginated but 3 "nicknames" only showing (this makes sense since pagination counted the output before group by) but how can I solve that? 我注意到,当使用will_paginate 20结果页面时,将多个表group_by“昵称”联接起来,但对输出进行分页,但是仅显示3个“昵称”(这是有道理的,因为分页是在group by之前对输出进行计数),但是我该如何解决呢? also, I want to display the output like that and limit the number of items per page based on "nickname" column: please note that the "data" table has many "preferences". 另外,我想显示这样的输出,并根据“昵称”列限制每页的项目数:请注意,“数据”表具有许多“首选项”。 (data.id = preferences.data_id) (data.id = preferences.data_id)

{
"totalCount": 123,
  "pageInfo": {
    "currentPage": 1,
    "nextPage": 2,
    "lastPage": 8
  },
  "results": [
    {
      "data": {
        "id": 1,
        "nickname": "foo"
      },
      "preferences": [
        {
          "id": 4479,
          "created_at": "2019-05-21T00:39:45.772Z",
          "updated_at": "2019-05-21T00:39:45.772Z",
          "title": "Check Database",
          ...
        },
        ...
      ]
    },
    ...
  ]
}

  data_res = Data.paginate(page: params[:page], per_page: 
  20).joins("INNER JOIN preferences ON data.id = 
  preferences.data_id").select("data.*, preferences.*").order(id: :asc)
  data_group_by = data_res.group_by { |r| r.nickname }
  respond_to do |format|
        format.any
        format.json {
          render :json => {
              :totalCount => data_res.total_entries,
              :pageInfo => {
                  :currentPage => data_res.current_page,
                  :nextPage => data_res.next_page,
                  :total_pages => data_res.total_pages,
                  :per_page => data_res.per_page,
              },
              :results =>  data_res
          }
        }
      end

If I'm understanding your question correctly(probably not), pagination says it has 20 records, but you're only seeing 3 records being returned because they're grouped? 如果我正确地理解了您的问题(可能不是),则分页显示它有20条记录,但是您只看到3条记录被归还了,因为它们已被分组了?

However, what you want is 20 records, with 20x preferences grouped? 但是,您想要的是20条记录,并且对20个首选项进行了分组?

If that's the case, I think you're probably overcomplicating your query. 如果是这样,我认为您可能会使查询过于复杂。

  1. I don't think you should use the select("data.*, preferences.*") because it basically just adds a new record per preference fetched, so the preferences is probably the determinant of how many records you're getting rather than data on which you're paginating on + you're dynamically adding additional methods to each of the data returned to account for the preferences 我认为您不应该使用select("data.*, preferences.*")因为它基本上只会为获取的每个首选项添加一条新记录,因此首选项可能是您要获取多少条记录的决定因素,而不是您要在其上进行分页的data +您正在向返回的每个数据动态添加其他方法以说明首选项
  2. data_res.group_by { |r| r.nickname } data_res.group_by { |r| r.nickname } seems unnecessary, unless you have data records that are not unique, in which case I'd question the reason for grouping them by that. data_res.group_by { |r| r.nickname }似乎是不必要的,除非您的数据记录不是唯一的,在这种情况下,我会质疑将其分组的原因。

In my opinion, if nicknames are unique, ie there can only be 1 data record with the same nickname , here's what I'd propose 我认为,如果昵称是唯一的,即只能有1个具有相同nickname data记录,这就是我的建议

class Data
   has_many :preferences
end
class Preference
   belongs_to :data
end

joins-ing and includes-ing here to ensure the preferences are eager loaded, while conforming to your existing query of only fetching data with preferences 在此处联接和包含以确保渴望加载首选项,同时符合仅获取具有首选项数据的现有查询

data_res = Data.joins(:preference).includes(:preference).paginate(page: params[:page], per_page: 20).order(id: :asc) # this should give you 20 records of data that has preferences

Then your serializer can do the rest of work to ensure your data is properly mapped and that your preferences are on the same level(there are several ways to achieve that with any serialization package), eg 然后,您的序列化程序可以完成其余工作,以确保正确映射数据并确保您的首选项处于同一级别(使用任何序列化程序包均可实现多种方式),例如

class DataPreferencesSerializer < AMS
  attributes :data
             :preferences # or can be has_many :preferences serializer
  def data
   {id: object.id, nickname: object.nickname }
  end

  def preferences
   object.preferences
  end
end

results= ArraySerializer.new(data_res, each_serializer: DataPreferencesSerializer, root: false)

Like I said, there are several ways of achieving the serialization, so the implementation above is just an idea of the approach you might take and not a specific implementation. 就像我说的那样,有几种方法可以实现序列化,因此上面的实现只是您可能采用的方法的一个想法,而不是特定的实现。

PS: Your INNER JOIN ensures that all the returned data records have an associated preferences , so any data that doesn't have at least one preference that is probably excluded from the records you get back. PS:你的INNER JOIN确保所有返回的data记录具有关联的preferences ,因此,任何data不具有至少一个preference是可能从你回来的记录排除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM