简单 SQL 查询 在野狗中的对应实现

2016-05-05 19:36:26 +08:00
 wilddog

野狗实时后端云主要提供的是一个实时通信的通道,但是毕竟也提供了数据存储的功能。因此野狗也可以被看作是一个具有实时同步数据功能的云端数据库。

这个数据库是 NoSQL 的,数据的存储是树型的,类似一个巨大的 JSON ,而不是关系型的二维表结构。对于有 SQL 技术背景的用户来说,使用野狗需要一个思维转换的过程。需要注意的是,虽然今天我们来讨论一些常见的 SQL 查询在野狗中如何对应的实现,我们仍然不建议待着关系型数据库的思维使用野狗云。

我们将会讨论如下几种查询:

我们同样以 JavaScript 为例, Android 和 iOS 平台类似。本文中所讲述的内容严重依赖于下列 API 的正确理解和使用,对这些 API 还不了解的用户,请参考 API 文档( https://z.wilddog.com/web/api):

根据一个用户的 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()等方法增加筛选条件,只对较少数据量进行“内层查询”。野狗为实时进行了许多优化,只要数据量不是太大,实时性和性能就不用太担心。

本文中我们讲述了一些最简单和基础的查询,更多高级查询和特性我们将在后续的文章中为大家讲述。

关注野狗官方微信,获取更多技术干货

1364 次点击
所在节点    问与答
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/276603

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX