栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaScript如何在Firebase中写入非规范化数据

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaScript如何在Firebase中写入非规范化数据

好问题。我知道三种解决方法,下面将列出。

我将为此使用一个稍微不同的示例,主要是因为它允许我在解释中使用更具体的术语。

假设我们有一个聊天应用程序,其中存储了两个实体:消息和用户。在显示消息的屏幕中,我们还显示用户名。因此,为了最大程度地减少读取次数,我们还将在每个聊天消息中存储用户名。

users  so:209103    name: "Frank van Puffelen"    location: "San Francisco, CA"    questionCount: 12  so:3648524    name: "legolandbridge"    location: "London, Prague, Barcelona"    questionCount: 4messages  -Jabhsay3487    message: "How to write denormalized data in Firebase"    user: so:3648524    username: "legolandbridge"  -Jabhsay3591    message: "Great question."    user: so:209103    username: "Frank van Puffelen"  -Jabhsay3595    message: "I know of three approaches, which I'll list below."    user: so:209103    username: "Frank van Puffelen"

因此,我们将用户配置文件的主副本存储在

users
节点中。在消息中,我们存储
uid
(so:209103和so:3648524),以便我们可以查找用户。但是,我们还将用户的名称存储在消息中,因此,当我们要显示消息列表时,不必为每个用户查找此名称。

现在,当我转到聊天服务上的“个人资料”页面并将我的名字从“ Frank van Puffelen”更改为“ puf”时,会发生什么。

交易更新

最初,大多数开发人员可能会想到执行事务更新。我们始终希望

username
in消息与
name
相应配置文件中的in 匹配。

使用多路径写入 (在20150925上添加)

从Firebase 2.3(针对Javascript)和2.4(针对Android和iOS)开始,您可以使用单个多路径更新来轻松实现原子更新:

function renameUser(ref, uid, name) {  var updates = {}; // all paths to be updated and their new values  updates['users/'+uid+'/name'] = name;  var query = ref.child('messages').orderByChild('user').equalTo(uid);  query.once('value', function(snapshot) {    snapshot.forEach(function(messageSnapshot) {      updates['messages/'+messageSnapshot.key()+'/username'] = name;    })    ref.update(updates);  });}

这将向Firebase发送一个更新命令,该命令将更新其个人资料和每条消息中的用户名。

先前的原子方法

因此,当用户更改

name
了个人资料中的时:

var ref = new Firebase('https://mychat.firebaseio.com/');var uid = "so:209103";var nameInProfileRef = ref.child('users').child(uid).child('name');nameInProfileRef.transaction(function(currentName) {  return "puf";}, function(error, committed, snapshot) {  if (error) {     console.log('Transaction failed abnormally!', error);  } else if (!committed) {    console.log('Transaction aborted by our pre.');  } else {    console.log('Name updated in profile, now update it in the messages');    var query = ref.child('messages').orderByChild('user').equalTo(uid);    query.on('child_added', function(messageSnapshot) {      messageSnapshot.ref().update({ username: "puf" });    });  }  console.log("Wilma's data: ", snapshot.val());}, false );

精打细算,精明的读者会注意到我在处理消息时作弊。首先作弊的是,我从不要求

off
侦听器,但我也不使用事务。

如果我们想从客户端安全地进行此类操作,则需要:

  1. 确保两个地方名称匹配的安全规则。但是规则需要允许足够的灵活性,以便它们在我们更改名称时暂时有所不同。因此,这变成了一个非常痛苦的两阶段提交方案。
    1. username
      消息的所有字段更改
      so:209103
      null
      (有些不可思议的值)
    2. name
      用户的更改
      so:209103
      为“ puf”
    3. 更改
      username
      每则消息中的
      so:209103
      null
      puf
    4. 该查询需要满足以下
      and
      两个条件之一,Firebase查询不支持这些条件。因此,我们将获得一个可以查询的额外属性
      uid_plus_name
      (具有value
      so:209103_puf
      )。
  2. 客户端代码以事务方式处理所有这些转换。

这种方法使我的头部受伤。通常,这意味着我做错了事。但是,即使这是正确的方法,但头部受伤,我更有可能犯编码错误。所以我更喜欢寻找一个更简单的解决方案。

最终一致性

:Firebase发布了一项功能,允许对多个路径进行原子写入。这与下面的方法类似,但是使用单个命令。请参阅上面的更新部分,以了解其工作原理。

第二种方法取决于将用户操作(“我想将我的名字更改为’puf””)与该操作的含义(“我们需要在profile:209103中以及每个包含的消息中更新名称)分开”

user = so:209103

我将在服务器上运行的脚本中处理重命名。主要方法如下:

function renameUser(ref, uid, name) {  ref.child('users').child(uid).update({ name: name });  var query = ref.child('messages').orderByChild('user').equalTo(uid);  query.once('value', function(snapshot) {    snapshot.forEach(function(messageSnapshot) {      messageSnapshot.update({ username: name });    })  });}

我在这里再次使用了一些捷径,例如使用

once('value'
(使用Firebase获得最佳性能通常不是一个好主意)。但是总体而言,此方法更简单,但代价是无法同时完全更新所有数据。但是最终,消息将全部更新以匹配新值。

不在乎

第三种方法是最简单的方法:在许多情况下,您根本不需要更新重复的数据。在我们这里使用的示例中,您可以说每个消息都记录了我当时使用的名称。直到现在我都没有更改我的名字,所以有意义的是,较旧的消息会显示我当时使用的名称。这在二级数据本质上是事务性的许多情况下适用。当然,它并不是在所有地方都适用,但是在所有情况下,“不关心”是最简单的方法。

摘要

尽管以上只是对如何解决此问题的广泛描述,但是它们肯定还不完整,但我发现,每次需要散出重复数据时,它都会回到这些基本方法之一。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/432208.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号