Подтвердить что ты не робот

Разбиение страниц в CouchDB?

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

Это то, к чему я придумал, - чтобы получить идентификаторы всех сообщений, а затем получить фактические элементы для первого числа 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

Ответ 4

  • Вот ниже рекурсивный способ, который я нашел:

    Взять две переменные

  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();

                           });
  });

  }