سؤال

كيف يمكنني تنفيذ الاستعلامات المطلوبة لترقيم الصفحات؟

بشكل أساسي، عند طلب الصفحة 1، احصل على أول 5 إدخالات.بالنسبة للصفحة 2، احصل على الـ 5 التالية وهكذا.

أخطط لاستخدام هذا من خلال وحدة Couchdb-Python، ولكن هذا لا ينبغي أن يحدث أي فرق في التنفيذ.

هل كانت مفيدة؟

المحلول

ال دليل كاوتش دي بي لديه مناقشة جيدة حول ترقيم الصفحات، بما في ذلك الكثير من نماذج التعليمات البرمجية، هنا: http://guide.couchdb.org/draft/recipes.html#paginationها هي الخوارزمية الخاصة بهم:

  • طلب rows_per_page + 1 صفوف من العرض
  • عرض rows_per_page الصفوف، تخزين الصف الأخير باسم next_startkey
  • كمعلومات الصفحة، احتفظ بها startkey و next_startkey
  • استخدم ال next_* القيم لإنشاء الارتباط التالي، واستخدام الآخرين لإنشاء الارتباط السابق

ملحوظة:الطريقة الصحيحة لجلب الصفحات في CouchDB هي تحديد مفتاح البداية، وليس فهرس البداية كما قد تعتقد.ولكن كيف تعرف المفتاح الذي تبدأ به الصفحة الثانية؟الحل الذكي:"بدلاً من طلب 10 صفوف للصفحة، يمكنك طلب 11 صفًا، ولكن يتم عرض 10 صفوف فقط واستخدام القيم الموجودة في الصف الحادي عشر كمفتاح بدء للصفحة التالية."

إذا كنت تتوقع أن تصدر مستندات متعددة مفاتيح متطابقة، فستحتاج إلى استخدام startdocid بالإضافة إلى startkey لترقيم الصفحات بشكل صحيح.والسبب هو أن startkey وحدها لن تكون كافية لتحديد صف بشكل فريد.هذه المعلمات عديمة الفائدة إذا لم تقم بتوفير ملف startkey.في الواقع، سوف يقوم CouchDB أولاً بإلقاء نظرة على ملف startkey المعلمة، ثم سيتم استخدام startdocid المعلمة لإعادة تعريف بداية النطاق بشكل أكبر إذا كانت صفوف التحديق المحتملة المتعددة لها نفس المفتاح ولكن معرفات مستند مختلفة.نفس الشيء بالنسبة ل enddocid.

نصائح أخرى

HTTP API مشاهدة يعطي مجالا واسعا للقيام الترحيل بكفاءة.

وأبسط طريقة سوف تستخدم startkey وcount. العد هو العدد الأقصى من إدخالات سوف كاوتش دي بي العودة لهذا الطلب الرأي، وهو ما يرجع إلى التصميم الخاص بك، وstartkey هو المكان الذي تريد كاوتش دي بي للبدء. عند طلب رأي وسوف اقول لك أيضا كم عدد الإدخالات هناك، مما يسمح لك لحساب عدد الصفحات سوف يكون هناك إذا كنت تريد أن تظهر أن للمستخدمين.

وهكذا فإن الطلب الأول لم تحدد startkey، مجرد العد لعدد الإدخالات التي تريد إظهارها. يمكنك ثم لاحظ مفتاح الإدخال الأخير عاد واستخدام ذلك كمفتاح بداية لصفحة المقبلة. في هذا النموذج البسيط، وسوف تحصل على التداخل، حيث الإدخال الأخير من صفحة واحدة هو الأول المقبل. إذا كان هذا غير مرغوب فيه هو تافهة لمجرد عدم عرض الإدخال الأخير من الصفحة.

وهناك طريقة أسهل للقيام بذلك هو استخدام المعلمة تخطي إلى العمل على مستند البداية للصفحة، ولكن يجب استخدام هذه الطريقة بحذر. يؤدي المعلمة تخطي ببساطة محرك داخلي لن يعود إدخالات أنها بالتكرار عبر. في حين أن هذا يعطي السلوك المطلوب هو أبطأ بكثير من العثور على أول وثيقة للصفحة بواسطة مفتاح. لمزيد من المستندات التي يتم تخطي، فإن تباطؤ الطلب أن يكون.

وهذا هو ما كنت قد خرجت حتى الآن - للحصول على هويات جميع المشاركات، ثم استرداد العناصر الفعلية لعدد خ الأول من معرفات ..

وانها ليست رهيبة كفاءة، بل أكثر من ذلك من استرجاع جميع الوظائف، ثم رمي معظم بعيدا. قال ذلك، لدهشتي، على ما يبدو لتشغيل بسرعة - ركضت طريقة 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