will_paginate в рельсах при использовании join и group by - PullRequest
0 голосов
/ 23 мая 2019

Я заметил, что при использовании will_paginate 20 приводит к созданию страницы, объединяющей несколько таблиц group_by "nickname", выходные данные разбиваются на страницы, но отображаются только 3 "псевдонима" (это имеет смысл, поскольку разбиение на страницы подсчитывало выходные данные перед group by), но как я могу это сделать?решить это?Кроме того, я хочу отображать вывод и ограничивать количество элементов на странице на основе столбца «псевдоним»: обратите внимание, что таблица «данных» имеет много «предпочтений».(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

1 Ответ

2 голосов
/ 23 мая 2019

Если я правильно понимаю ваш вопрос (возможно, нет), нумерация страниц говорит, что у него 20 записей, но вы видите только 3 возвращаемых записи, потому что они сгруппированы?

Тем не менее, что вы хотите - это 20 записей, сгруппированные по 20x предпочтениям?

Если это так, я думаю, вы, вероятно, слишком усложняете свой запрос.

  1. Я не думаю, что вам следует использовать select("data.*, preferences.*"), потому что он просто добавляет новую запись для каждой выбранной настройки, поэтому предпочтения, вероятно, являются определяющим фактором того, сколько записей вы получаете, а не data, на которых вы нумерация страниц + вы динамически добавляете дополнительные методы к каждому из данных, возвращаемых для учета предпочтений
  2. data_res.group_by { |r| r.nickname } кажется ненужным, если только у вас нет не уникальных записей данных, и в этом случае я бы поставил под сомнение причину их группировки по этому.

По моему мнению, если псевдонимы уникальны, то есть может быть только 1 data запись с тем же nickname, вот что я бы предложил

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

присоединяется и включается здесь, чтобы убедиться, что настройки загружены, в то время как в соответствии с вашим существующим запросом только выборка данных с настройками

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

Тогда ваш сериализатор может выполнить всю остальную работу, чтобы убедиться, что ваши данные правильно сопоставлены и ваши предпочтения находятся на одном уровне (есть несколько способов добиться этого с любым пакетом сериализации), например,

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)

Как я уже сказал, существует несколько способов достижения сериализации, поэтому приведенная выше реализация - это всего лишь идея подхода, который вы можете использовать, а не конкретная реализация.

PS: Ваш INNER JOIN гарантирует, что все возвращенные записи data имеют ассоциированные preferences, поэтому любой data, который не имеет хотя бы одного preference, вероятно, исключен из записей, которые вы получаете назад.

...