野狗实时后端云主要提供的是一个实时通信的通道,但是毕竟也提供了数据存储的功能。因此野狗也可以被看作是一个具有实时同步数据功能的云端数据库。
这个数据库是NoSQL的,数据的存储是树型的,类似一个巨大的JSON,而不是关系型的二维表结构。对于有SQL技术背景的用户来说,使用野狗需要一个思维转换的过程。需要注意的是,虽然今天我们来讨论一些常见的SQL查询在野狗中如何对应的实现,我们仍然不建议待着关系型数据库的思维使用野狗云。
我们将会讨论如下几种查询:
- 根据一个用户的id查询用户(WHERE id = x)
- 根据email查询用户(WHERE email = x)
- 查询昨天发表的消息(WHERE time BETWEEN x AND y)
- 排序取x条(ORDER BY time LIMIT x)
- 通过id字段关联查询(FROM table1 JOIN table2 USING id)
我们同样以JavaScript为例,Android和iOS平台类似。本文中所讲述的内容严重依赖于下列API的正确理解和使用,对这些API还不了解的用户,请参考API文档( https://z.wilddog.com/web/api):
- orderByChild:按照指定子节点的值排序。
- startAt:查询值范围的起点。如果没有明确的指定orderBy属性,则默认按照数据的priority排序。
- endAT:与startAt对应,查询值范围的结束点。
- limitToFirst/limitToLast:返回多少条数据记录,相当与sql中的limit。
根据一个用户的id查询用户(WHERE id = x)
根据id查询用户,这是最基础的查询。在野狗中,所有的数据都拥有一个唯一的URL,数据是存储在一个path路径下的,path中的字段名key即可被认为是记录的主键id。例如我们在/user路径下存储了每个用户的信息:
数据中的123,234,345,456就是四条记录的id。那么当根据id查询user的时候,我们只需要使用数据的URL进行查询:
var ref = new Wilddog(“https://.wilddogio.com/user/2”);
ref.once(‘value’, function(snapshot) {
console.log(‘I fetched a user!’, snapshot.val());
});
根据email查询用户(WHERE email = x)
使用id对数据进行查询是很简单的,因为id已经在数据的URL中。如果我们要查询的字段不再URL中呢?我们查找email为zhangsan@wilddog.com的用户,需要结合使用orderByChild()方法和startAt()和endAt()方法:
var ref = new Wilddog(“https://<appId>.wilddogio.com/user”);
ref.orderByChild(‘email’)
.startAt(‘zhangsan@wilddog.com’)
.endAt(‘zhangsan@wilddog.com’)
.once(‘value’, function(snapshot) {
console.log(‘accounts matching:’, snapshot.val())
});
查询昨天发表的消息(WHERE time BETWEEN x AND y)
假设数据结构如下:
要对time字段进行范围查询,同样结合使用orderByChild()方法和startAt()和endAt()方法:
ref.orderByChild(‘time’)
.startAt(startTime)
.endAt(endTime)
.once(‘value’, function(snapshot) {
console.log('messages found : ', snapshot.val())
});
排序取x条(ORDER BY time LIMIT x)
假设每个用户都有一个age字段,要按age排序,查询年龄最小的两个user,可以构造如下的查询:
var ref = new Wilddog(“https://<appId>.wilddogio.com”);
ref.child(‘user’).orderByChild(‘age’).limitToFirst(2).on(‘child_added’, function(userSnap) {
console.log('find user : ’ + JSON.stringify(userSnap.val()));
});
如果要取年龄最大的2个user,将limitToFirst(2)改为limitToLast(2)即可。
通过id字段关联查询(FROM table1 JOIN table2 USING id)
有时候我们出于查询性能的考虑,为了避免一次从云端传输太大的数据量,我们将一部分数据拆分出去存储在另外的数据路径下。假设我们的每位user都有自己的media属性,而我们将media属性拆分出去存储,数据如下:
这时候可能需要在查询的时候进行一个类似关系数据库中的JOIN查询:
var ref = new Wilddog(“https://<appId>.wilddogio.com”);
ref.child(‘user/123’).once(‘value’, function(userSnap) {
ref.child(‘media/123’).once(‘value’, function(mediaSnap) {
console.log(‘user:’ + userSnap.val().name + ', media : ’ + mediaSnap.val().weibo);
});
});
如果不是指定id为123的用户,而是查询所有的用户:
var ref = new Wilddog(“https://<appId>.wilddogio.com”);
ref.child(‘user’).on(‘child_added’, function(userSnap) {
var id = userSnap.key();
ref.child(‘media’).child(id).once(‘value’, function(mediaSnap) {
console.log(‘user:’ + userSnap.val().name + ', media : ’ + mediaSnap.val().weibo);
});
});
出于性能的考虑,在“关联查询”的时候,应当在“外层查询”使用startAt(),endAt()等方法增加筛选条件,只对较少数据量进行“内层查询”。野狗为实时进行了许多优化,只要数据量不是太大,实时性和性能就不用太担心。
本文中我们讲述了一些最简单和基础的查询,更多高级查询和特性我们将在后续的文章中为大家讲述。
关注野狗官方微信,获取更多技术干货
有 mongoose 的感觉