write - read from firebase database android




التعامل مع الكثير من البيانات في فيريباس لنظام ريكومندر (2)

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

وقد قلت ذلك، إذا كنت ترغب في تسريع الامور، يمكنك تعديل الخوارزمية الخاصة بك لموازنة جلب ومعالجة البيانات / الأفلام:

| fetch  | -> |process | -> | fetch  | ...
|chunk(1)|    |chunk(1)|    |chunk(3)|

(in parallel) | fetch  | -> |process | ...
              |chunk(2)|    |chunk(2)|

مع هذا النهج، يمكنك تجنيب تقريبا كل الوقت اللازم للتجهيز (ولكن الجزء الأخير) إذا تجهيز أسرع حقا من جلب (ولكن لم يقل كيف "سريع نسبيا" تشغيل خوارزمية الخاص بك، مقارنة بجلب جميع الأفلام)

هذا النهج "عالي المستوى" لمشكلتك هو على الأرجح فرصة أفضل إذا جلب الأفلام بطيئة حقا على الرغم من أنها تتطلب المزيد من العمل من مجرد تفعيل زر "تسريع" افتراضية للمكتبة. على الرغم من أنه هو نهج سليم عند التعامل مع جزء كبير من البيانات.

أنا بناء نظام ريكومندر حيث يمكنني استخدام فيريباس لتخزين واسترجاع البيانات حول الأفلام وتفضيلات المستخدم .

يمكن أن يكون لكل فيلم عدة سمات، وتبدو البيانات كما يلي:

{ 
    "titanic": 
    {"1997": 1, "english": 1, "dicaprio": 1,    "romance": 1, "drama": 1 }, 
    "inception": 
    { "2010": 1, "english": 1, "dicaprio": 1, "adventure": 1, "scifi": 1}
...
}

ولتقديم التوصيات، تتطلب خوارزميتي إدخال جميع البيانات (الأفلام) ومطابقتها مع ملف شخصي للمستخدم.

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

أنا استرداد البيانات على النحو التالي:

firebase.database().ref(moviesRef).on('value', function(snapshot) {
    // snapshot.val();
}, function(error){
    console.log(error)
});

أنا أتساءل عما إذا كان لديك أي أفكار حول كيفية تسريع الامور؟ هل هناك أي إضافات أو تقنيات معروفة لحل هذه المشكلة؟

أنا أدرك أن دنورماليزاشيون يمكن أن تساعد في تقسيم البيانات حتى، ولكن المشكلة هي حقا أنني بحاجة إلى جميع الأفلام وجميع السمات المقابلة.


اقتراحي سيكون استخدام وظائف الغيمة للتعامل مع هذا.

الحل 1 (مثالي)

إذا كان يمكنك حساب الاقتراحات كل ساعة / يوم / أسبوع

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

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

سيبدو رمز وظائف السحاب كما يلي:

var movies, allUsers; 

exports.weekly_job = functions.pubsub.topic('weekly-tick').onPublish((event) => {
  getMoviesAndUsers();
});  

function getMoviesAndUsers () {
  firebase.database().ref(moviesRef).on('value', function(snapshot) {
    movies = snapshot.val();
    firebase.database().ref(allUsersRef).on('value', function(snapshot) {
        allUsers = snapshot.val();
        createRecommendations();
    });
});
}

function createRecommendations () {
  // do something magical with movies and allUsers here.

  // then write the recommendations to each user's profiles kind of like 
  userRef.update({"userRecommendations" : {"reco1" : "Her", "reco2", "Black Mirror"}});
  // etc. 
}

يغفر رمز الزائفة. آمل أن يعطي هذا فكرة على الرغم من.

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

الحل 2

إذا كنت لا يمكن حساب الاقتراحات كل ساعة / يوم / أسبوع، وعليك أن تفعل ذلك في كل مرة المستخدم الوصول إلى توصيات لوحة

ثم يمكنك تشغيل وظيفة سحابة في كل مرة يقوم المستخدم بزيارة صفحة توصياتهم. حل الغش السريع يمكنني استخدام لهذا هو كتابة قيمة في الملف الشخصي للمستخدم مثل: {getRecommendations:true} ، مرة واحدة على باجيلود، ثم في وظائف سحابة الاستماع للتغييرات في getRecommendations . طالما لديك بنية مثل هذا:

أوسيريد> جيتريكومنداتيونس: ترو

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

[ رمز الواجهة ]

//on pageload
userProfileRef.update({"getRecommendations" : true});
userRecommendationsRef.on('value', function(snapshot) {  gotUserRecos(snapshot.val());  });

[ وظائف السحاب (رمز الخلفية) ]

exports.userRequestedRecommendations = functions.database.ref('/users/{uid}/getRecommendations').onWrite(event => {
  const uid = event.params.uid;
  firebase.database().ref(moviesRef).on('value', function(snapshot) {
    movies = snapshot.val();
    firebase.database().ref(userRefFromUID).on('value', function(snapshot) {
        usersMovieTasteInformation = snapshot.val();
        // do something magical with movies and user's preferences here.
        // then 
        return userRecommendationsRef.update({"getRecommendations" : {"reco1" : "Her", "reco2", "Black Mirror"}});
    });
  });
});

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

بس 1: انتهى بي الأمر باستخدام رمز أكثر الزائفة من المقصود أصلا، وإزالة معالجة الخطأ وما إلى ذلك على أمل أن هذا يحصل عموما على نقطة عبر. إذا كان هناك أي شيء غير واضح، والتعليق، وسأكون سعيدا لتوضيح.

بس 2: أنا باستخدام تدفق مماثل جدا لخدمة مصغرة الداخلية بنيت لأحد زبائني، وأنها كانت تعمل بسعادة لفترة أطول من شهر الآن.