V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
wilddog
V2EX  ›  问与答

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

  •  
  •   wilddog · 2016-05-05 19:36:26 +08:00 · 1353 次点击
    这是一个创建于 2916 天前的主题,其中的信息可能已经有所发展或是发生改变。

    SQL2.png

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

    这个数据库是 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 为 [email protected] 的用户,需要结合使用 orderByChild()方法和 startAt()和 endAt()方法:

    var ref = new Wilddog("https://<appid>.wilddogio.com/user");

    ref.orderByChild('email')

    .startAt('[email protected]')

    .endAt('[email protected]')

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

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

    qrcode_for_gh_55dcc2c31752_258 (2).jpg

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

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5221 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:01 · PVG 17:01 · LAX 02:01 · JFK 05:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.