עדכון אטומי בmongodb
-
שלום וברכה
יש לי טבלה (collection) בmongodb שמכיל אובייקטים בצורה הזאת:{ key:'key1', value:'3', exp:'2024-10-07T09:38:21.714Z', valueAfetrExp:'1' }
הפונקצייה אמור להיות העלאת ה value בסכום מסויים בצורה אטומית כך שלא יפקשש בקשות מקבילות על אותו key
הוא אמור להעלות רק אם הexp עדיין לא עבר ובמידה שכן שיעדכן את value במה שכתוב ב valueAfetrExp
במידה שלא כתוב כלום ב valueAfetrExp הוא אמור למחוק את האובייקט.ניסיתי להשתמש עם transaction הבעייה היא שבסקייל גבוה כל בקשה יכול להיות גם עשר דקות או אפילו יותר.
יש פיתרון אחר?אני מצרף חלק מהקוד של העדכון שיש לי כיום:
const setKey = async (key: string, newValue: string) => { await client.withSession(async session => { await session.withTransaction(async () => { const oldData = await Data.findOne({ key: 'key1' }, { session }); if (!oldData) throw new Error('Key not found'); //בדיקה אם עבר כבר הזמן if (oldData.exp && checkIfExpIsOver(oldData.exp)) { //הצבת הערך שיש ב valueAfetrExp ואם אין אז למחוק את האובייקט. } else { await Data.updateOne({ _id: oldData._id }, { $set: { value: String(Number(oldData.value) + Number(newValue)) } }, { session }); } }); }); }
-
@ivrtikshoret כתב בעדכון אטומי בmongodb:
ניסיתי להשתמש עם transaction הבעייה היא שבסקייל גבוה כל בקשה יכול להיות גם עשר דקות או אפילו יותר.
מה הכוונה? תוכל לפרט?
-
@צדיק-תמים כתב בעדכון אטומי בmongodb:
מה הכוונה? תוכל לפרט?
מה אתה רוצה שאני יפרט?
הוספתי את הקוד שמעדכן בפוסט הראשון -
@ivrtikshoret במחשבה נוספת, מה שאתה צריך זה לא טרנזקציה אלא להשתמש בinc, לא?
ולא ממש הבנתי את תפקיד הexp, אם הוא נועד למחיקה אחרי זמן מסוים, עדיף לעשות את זה דרך אינדקס TTL -
@צדיק-תמים כתב בעדכון אטומי בmongodb:
@ivrtikshoret במחשבה נוספת, מה שאתה צריך זה לא טרנזקציה אלא להשתמש בinc, לא?
ולא ממש הבנתי את תפקיד הexp, אם הוא נועד למחיקה אחרי זמן מסוים, עדיף לעשות את זה דרך אינדקס TTLלגבי האופצייה הראשונה אני צריך לבדוק לפני האם התפוגה עבר כבר וכן מה שכתבתי על השאלה השנייה
לגבי השאלה השנייה לא תמיד הוא מוחק אלא אם יש משהו ב valueAfetrExp אני לא מוחק אלא מציב ב value את מה שכתוב ב valueAfetrExp ולכן אני לא יכול להשתמש עם אינדקס TTL -
@ivrtikshoret אני לא מבין למה הטרנזציה איטית, אבל אתה יכול לבצע את כל הלוגיקה דרך mongodb באמצעות מה שנקרא aggregation pipeline, ואז זה אטומי בלי טרנזציה, משהו כזה (גילוי נאות, השאילתה נכתבה ע"י claude.ai) :
const setKey = async (key: string, newValue: string): Promise<void> => { const currentDate = new Date(); const newExp = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 שעות מעכשיו const result = await Data.findOneAndUpdate( { key: key }, [ { $set: { isExpired: { $gt: [currentDate, '$exp'] } } }, { $set: { value: { $cond: { if: { $not: ['$isExpired'] }, then: { $add: [{ $toInt: '$value' }, { $toInt: newValue }] }, else: { $cond: { if: { $ne: ['$valueAfterExp', null] }, then: '$valueAfterExp', else: '$value' } } } }, exp: { $cond: { if: { $not: ['$isExpired'] }, then: '$exp', else: newExp } }, valueAfterExp: { $cond: { if: { $not: ['$isExpired'] }, then: '$valueAfterExp', else: null } } } }, { $unset: 'isExpired' } ], { returnDocument: 'after' } ); if (!result.value) { throw new Error('Key not found'); } // מחיקת האובייקט אם אין valueAfterExp ופג תוקפו if (checkIfExpIsOver(result.value.exp as Date) && !result.value.valueAfterExp) { await Data.deleteOne({ _id: result.value._id }); } };
-
@ivrtikshoret בעניותי עוד לא הבנתי למה אי אפשר להשתמש ב-
inc
הבדיקה אם התאריך פג לא צריך להיות אטומי -
@yossiz
בעצם מה שאתה אומר דבר ראשון לשלוף את הנתונים הקיימים כרגע ולבדוק את התוקף במידה שכרגע אנחנו עדיין לפני התוקף אז לבצע עדכון עם inc,
צודק אני מנסה לחשוב למה לא עשיתי את זה,
בנתיים ננסה לעשות את זה אם זה יעבור את הטסטים אז מצוין, תודה מראש!