Вопрос

Как бы я приступил к реализации запросов, необходимых для разбивки на страницы?

В принципе, когда запрашивается страница 1, получите первые 5 записей.Для страницы 2 найдите следующие 5 и так далее.

Я планирую использовать это через модуль couchdb-python, но это не должно иметь никакого значения для реализации.

Это было полезно?

Решение

Тот Самый Руководство CouchDB здесь есть хорошее обсуждение разбивки на страницы, включая множество примеров кода: http://guide.couchdb.org/draft/recipes.html#pagination Вот их алгоритм:

  • Запрос rows_per_page + 1 строки из представления
  • Дисплей rows_per_page строки, сохраните последнюю строку как next_startkey
  • В качестве информации о странице сохраните startkey и next_startkey
  • Используйте next_* значения для создания следующей ссылки и используйте остальные для создания предыдущей ссылки

Н.Б.:Правильный способ извлечения страниц в CouchDB - это указать начальный ключ, а не начальный индекс, как вы могли бы подумать.Но откуда вы знаете, с какой клавиши начинать 2-ю страницу?Умное решение:"Вместо запроса 10 строк для страницы вы запрашиваете 11 строк, но отображаете только 10 и используете значения в 11-й строке в качестве начальной клавиши для следующей страницы".

Если вы ожидаете, что несколько документов будут выдавать одинаковые ключи, вам нужно будет использовать startdocid в дополнение к startkey для правильной разбивки на страницы.Причина в том, что startkey одного этого уже будет недостаточно для однозначной идентификации строки.Эти параметры бесполезны, если вы не предоставляете startkey.Фактически, CouchDB сначала рассмотрит startkey параметр, то он будет использовать startdocid параметр для дальнейшего переопределения начала диапазона, если несколько потенциальных начальных строк имеют один и тот же ключ, но разные идентификаторы документа.То же самое относится и к enddocid.

Другие советы

CouchDB API HTTP View предоставляет множество возможностей для эффективной подкачки страниц.

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

Таким образом, в первом запросе не будет указана начальная клавиша, а будет только количество записей, которые вы хотите показать. Затем вы можете отметить ключ последней возвращенной записи и использовать его в качестве ключа запуска для следующей страницы. В этой простой форме вы получите перекрытие, при котором последняя запись на одной странице является первой из следующей. Если это нежелательно, просто не отображать последнюю запись на странице.

Более простой способ сделать это - использовать параметр skip для обработки начального документа для страницы, однако этот метод следует использовать с осторожностью. Параметр skip просто заставляет внутренний движок не возвращать записи, которые он перебирает. Хотя это дает желаемое поведение, это намного медленнее, чем поиск первого документа для страницы по ключу. Чем больше документов будет пропущено, тем медленнее будет запрос.

Это то, что я придумал до сих пор - получить идентификаторы всех сообщений, а затем извлечь фактические элементы для первого x количества идентификаторов.

Это не очень эффективно, но более важно, чем извлекать все сообщения, а затем отбрасывать большую часть. Тем не менее, к моему удивлению, он, кажется, работает довольно быстро - я запустил метод posthelper.page () 100 раз, и это заняло около 0,5 секунды.

Я не хотел публиковать это в актуальном вопросе, так что это не повлияло бы на ответы так много - вот код:

allPostsUuid = """
function(doc) {
if(doc.type == 'post'){
    emit(doc._id, null);
}
}
"""

class PostsHelper:
    def __init__(self):
        server = Server(config.dbhost)
        db = server[config.dbname]
        return db


    def _getPostByUuid(self, uuid):
        return self.db.get(uuid)

    def page(self, number = 1):
        number -= 1 # start at zero offset
        start = number * config.perPage
        end = start + config.perPage

        allUuids = [
            x.key for x in self.db.query(allPostsUuid)
        ]
        ret = [
            self._getPostByUuid(x) for x in allUuids[start : end]
        ]

        if len(ret) == 0:
            raise Error404("Invalid page (%s results)" % (len(allUuids)))
        else:
            return ret
  • Вот ниже приведен рекурсивный способ, который я нашел :

    Возьмем две переменные

  var lastOffset = 0; var counter = 0;

  function someRecursive(lastOffset,counter) {

  queryView(db, whereClause).then(result => {
      var rows_per_page = 5; 

//formula below 
var page = Math.floor((lastOffset == 0 ? 0: (result.offset - lastOffset) +

  (rows_per_page * counter)) /  rows_per_page) + 1;

   var skip = page * rows_per_page;
  if (somerecursionexitcondition) {
                   counter = lastOffset == 0 ? lastOffset: counter + 1;
                   lastOffset =result.offset;
              someRecursive(lastOffset, counter).then(result => {
                               resolve();

                           });
  });

  }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top