热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在野狗中实现Count和自增字段

野狗并没有提供一个类似于count()的API。当我们需要知道某个数据节点下有多少个子节点的时候,有两种方式来实现:当数据量不大的时候,可以在客户端进行计数当数据量较大的时候,在野狗云端

野狗并没有提供一个类似于count()的API。当我们需要知道某个数据节点下有多少个子节点的时候,有两种方式来实现:


  • 当数据量不大的时候,可以在客户端进行计数

  • 当数据量较大的时候,在野狗云端记录一个计数器


由于Javascript语言比较容易运行和调试,我们以Javascript SDK为例来解决这个问题,Android和iOS端可以实现相同的效果。


在客户端计数


假设一个这样的场景,我们有一个/books数据节点,通过push()方法在其下存储了许多书籍的信息,我们将每本书的信息称之为一条“记录”,数据结构如下:



我们先假设记录条数量很少,采用客户端计数的方案。需要注意的是,使用child_added事件是无法实现这个计数需求的:


var ref = new Wilddog("https://.wilddogio.com/books");

var counter = 0;

ref.on('child_added', function(snapshot) {

console.log(snapshot.val().name);

counter ++;

});


在上面的代码中,由于child_added事件会为每个子节点触发一次,因此我们试图用一个counter字段作为计数器来计算总记录的条数。这个方案看起来还可以,但是问题出在异步上,每此回调函数被触发执行,我们都无法知道这是否是最后一条记录。


正确的做法是使用value事件:


var ref = new Wilddog("https://.wilddogio.com/books");


ref.on('value', function(snapshot) {

    var count = 0;

    snapshot.forEach(function() {

        count++;

    });

    console.log(count);  // 此时的count是可靠的

});


上面的代码可以准确的统计到记录的条数,其实还有一个更简单的API,不需要使用forEach循环计数,直接调用snapshot的numChildren()方法就可以了。这是小数据量的时候最好的方法了,非常简单。


在云端计数


遗憾的是实际的应用开发中,大部分时候我们都会考虑数据量比较大,全部加载到客户端进行计数是效率非常低,甚至完全不可行的。我们可以在云端记录一个计数器的方式来实现。我们在books节点下增加一个count节点,代表记录的条数,数据结构如下:



接下来,在每次push()一条新的记录的时候,我们都对counter字段进行+1:


var ref = new Wilddog("https://.wilddogio.com/books");

ref.push({"name":'new book'});

ref.child('counter').once('value', function(snapshot) {

var count = snapshot.val();

counter ++;

ref.child('counter').set(count);

});


这是最简单最直观的实现。但是它只适用于没有并发访问,或者对count数据的精确度要求不高的场景下。因为这里的push一条数据和修改counter的值是两个操作,而且修改counter的值是一种“读出来,加1,写回去”的模式,在多个终端用户同时操作的情况下会出现并发问题导致数据错误。


要解决并发修改数据的问题,需要使用野狗的transaction API。这里的transaction和关系型数据库中事务不是一回事。关系型数据库中的事务是为了保证ACID四个特性,而野狗的transaction API只是用来保证在多个客户端同时修改一个数据时不会产生冲突,可以实现对数据更改的原子性操作。使用transaction后的代码实现如下:


ref.child('counter').transaction(function(currentValue) {

    var newValue = (currentValue||0) + 1;

    return newValue;

}, function(err, committed, snapshot) {

    if (err) {

   console.log("err: " + err);

    } else if (committed) {

   ref.push({"name":'a new book'});

    }

});


transaction() 方法接受2个回调函数作为参数。第一个函数将会获取到当前的值,return的是即将被写入的值。这里我们对counter进行+1操作。第二个回调函数中的committed为true时,代表这个transaction已经成功,此时我们push一条新的记录。


transaction()的原理是,在向云端写入newValue的时候,会判断云端的数据仍然是旧的currentValue。如果云端数据已被其他客户端修改掉了,那么这次请求就会失败并重试。重试的过程是,重新从云端获取数据的值,记为currentValue,重新计算新值(+1),重新向云端写入。这个过程一直重复直至写入成功,或者超过最大重试次数。这些工作都是野狗SDK内部完成了的,我们无需关心其原理,只要根据文档,知道API的用法就可以了。


实现自增字段


有了计数器的实现,稍加修改就可以实现自增字段了。我们可以将counter字段作为一个id的发号器,用它来生成自增的id。假如我们不再使用push()方法存储每本书的数据(push会为每条记录生成唯一的key,就是数据中以-K开头的字符串),而是自行维护一个自增的“主键”。我们将写入数据的程序修改如下:


ref.child('counter').transaction(function(currentValue) {

    return (currentValue||0) + 1;

}, function(err, committed, snapshot) {

    if (err) {

   console.log("err: " + err);

    } else if (committed) {

   var id = snapshot.val();

   ref.child(id).set({"name":'a new book'});

    }

});


执行的过程是,第一个回调函数将counter的值+1,成功之后进入第二个回调函数中,commited为true,snapshot为+1之后的counter的值,也就是获得了最新的id。不再使用push,而是child(id)之后去set()数据就可以了。结果如下:


这样我们就实现了自增字段。



转载自:https://sanwen8.cn/p/1a7EJbE.html


推荐阅读
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
author-avatar
陈家小女u
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有