作者:尘世聚散 | 来源:互联网 | 2023-02-09 11:14
我正在构建一个推荐系统,我使用Firebase存储和检索有关电影和用户首选项的数据.
每部电影都有几个属性,数据如下:
{
"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加载这些数据需要花费大量时间.
我检索数据如下:
firebase.database().ref(moviesRef).on('value', function(snapshot) {
// snapshot.val();
}, function(error){
console.log(error)
});
我想知道你是否对如何加快速度有任何想法?是否有任何已知的插件或技术可以解决这个问题?
我知道非规范化可以帮助分割数据,但问题是我需要所有电影和所有相应的属性.
1> johnozbay..:
我的建议是使用云功能来处理这个问题.
解决方案1(理想情况下)
如果您可以每小时/每天/每周计算建议
您可以使用Cloud Functions Cron每天/每周启动,并计算每周/每天每位用户的建议.通过这种方式,您可以获得与Spotify与其每周播放列表/推荐相似的结果.
这样做的主要优点是您的用户不必等待所有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
.只要你有这样的结构:
userID> getRecommendations:true
如果您有适当的安全规则,以便每个用户只能写入其路径,则此方法将为您提供正确的userID以发出请求.因此,您将知道要为哪些用户计算建议.云功能最有可能更快地提取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
,因此只要您的云功能完成,您的用户就会看到结果.这可能需要几秒钟,因此请考虑使用加载指示器.
PS 1:我最终使用了比原先预期更多的伪代码,并删除了错误处理等等.希望这通常可以解决问题.如果有什么不清楚,评论,我会很乐意澄清.
PS 2:我正在使用一个非常类似的流程来为我的一个客户建立的迷你内部服务,并且现在已经开心运行了一个多月.