اذهب إلى المحتوى

السؤال

نشر

لدي مجموعة من المستندات ضمن قاعدة بيانات mongodb وأحاول الحصول عليها من خلال استخدام pymongo في بايثون:

for cursor in collection.find({ "$and" : [{ "users" : { "$gt" : 2000 } }, { "users" : { "$lt" : 3000 } }, { "is_like" : { "$exists" : False } }] }): 
    print cursor['username']
    print cursor['_id']['user_id']
    id = cursor['_id']['user_id']

ولكن بدأ يظهر لي الخطأ التالي:

pymongo.errors.CursorNotFound: cursor id '...' not valid at server.

لماذا أصبح يظهر لي هذا الخطأ؟ وكيف يمكنني حل المشكلة؟

Recommended Posts

  • 1
نشر

لقد تلقيت هذا الخطأ لأن المؤشر تنتهي مهلته على الخادم (بعد 10 دقائق من عدم النشاط).

من توثيق pymongo

اقتباس

يمكن أن تنتهي مهلة المؤشرات في MongoDB على الخادم إذا كانت مفتوحة لفترة طويلة دون إجراء أي عمليات عليها. يمكن أن يؤدي هذا إلى ظهور استثناء CursorNotFound عند محاولة تكرار المؤشر.

عندما تستدعي دالة collection.find  ، فإنه يستعلم مجموعة collection  ويعيد المؤشر إلى المستندات. 

للحصول على المستندات ، تقوم بتكرار المؤشر. عندما تقوم بالتكرار عللا المؤشر ، يقوم التعريف driver بالفعل بتقديم طلبات إلى خادم MongoDB لجلب المزيد من البيانات من الخادم.

 يتم تحديد مقدار البيانات التي يتم إرجاعها في كل طلب بواسطة دالة ()batch_size .

من توثيق mongo بخصوص دالة ()batch_size

اقتباس

يحد من عدد المستندات التي تم إرجاعها دفعة واحدة. تتطلب كل دفعة رحلة ذهابًا وإيابًا إلى الخادم. يمكن تعديله لتحسين الأداء والحد من نقل البيانات.

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

حجم الدفعة الافتراضي batch size :

اقتباس

بالنسبة لمعظم الاستعلامات ، تقوم الدفعة الأولى بإرجاع 101 مستند أو مستندات كافية فقط لتتجاوز 1 ميغا بايت. لن يتجاوز حجم الدفعة الحد الأقصى لحجم مستند BSON (16 ميجابايت).

لا يوجد حجم دفعة قياسي "صحيح".

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

سيكون الملاذ الأخير هو تعيين no_cursor_timeout=True. 

لكن عليك التأكد من إغلاق المؤشر بعد الانتهاء من معالجة البيانات.

كيفية تجنبها بدون try/except :

cursor = collection.find(
     {"x": 1},
     no_cursor_timeout=True
)
for doc in cursor:
    # do something with doc
cursor.close()

 

  • 1
نشر

تحدث هذه المشكلة بسبب عدم إستخدام الإتصال بالخادم لمدة أكثر من 10 دقائق، ويمكن حل المشكلة من خلال تمرير المدخل no_cursor_timeout بقيمة True كالتالي:

cursor  = collection.find({ "$and" : [{ "users" : { "$gt" : 2000 } }, { "users" : { "$lt" : 3000 } }, { "is_like" : { "$exists" : False } }] }, no_cursor_timeout=True)
for i in cursor:
    pass

cursor.close() # إنهاء الإتصال

لاحظ أنه يجب عليك إنهاء الإتصال بنفسك لكي تتجنب إستهلاك الموارد

  • 1
نشر

لحل المشكلة بشكل دائم، يمكن تحديد time out عام كبير:

use admin 
db.runCommand({setParameter:1, cursorTimeoutMillis: 1800000})

إن كنت تستخدم terminal:

sudo mongod --setParameter cursorTimeoutMillis=10800000

إن كان عدد المستندات المعاد كبير هذا ربما يؤدي لمكشلة فيمكن تحديد عدد صغير نسبيا..

find().batch_size(20)

ولإلغاء time out على مستوى الاتصال:

col.find(timeout=False)

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...