组织数据 编辑文档

本篇文档介绍如何恰当构建 Wilddog Sync 数据存储结构,以降低数据查询难度,提高查询速度。

理解数据结构

Wilddog Sync 数据结构类似 NoSQL 类型,数据以 JSON 为格式进行存储。没有传统关系型数据库中的表和记录等概念。

{
"users": {
"Mchen": {
"friends": { "Jack": true },
"name": "Mary Chen",
"widgets": { "one": true, "three": true }
},
"Jack": { ... },
"Harry": { ... }
}
}

使数据扁平化

Wilddog Sync 的工作方式是当你查询某个节点时,将会返回这个节点下的所有子节点。所以,如果采取过多嵌套的数据结构,在查询时会返回很多冗余数据。

例如,你只想查询所有 room 的 name、type 信息,但下面的结构会返回不需要的 messages 列表。

{
// 一个非常差的充满嵌套的数据结构。请勿模仿。
// 对"rooms"进行遍历查找来获得名字需要下载很多很多的 messages。
"rooms": {
"one": {
"name": "room alpha",
"type": "private",
"messages": {
"m1": { "sender": "mchen", "message": "foo" },
"m2": { ... },
// 非常长的 messages 列表
}
},
"two":{...}
}
}

正确的做法如下,应该尽量使数据扁平化,让数据分布到不同的路径下,提高查询效率。

{
// rooms数据节点下仅包含房间的基本信息和唯一ID。
"rooms": {
"one": {
"name": "room alpha",
"type": "private"
},
"two": { ... },
"three": { ... }
},

//room成员可以很方便的的存取
"members": {
"one": {
"Mchen": true,
"Harry": true
},
"two": { ... },
"three": { ... }

},

//消息数据与其他数据分离开,这样我们在查询其他数据时就不收消息数据的影响,从而提升性能。
//消息数据可以通过room ID方便的分页和查询。
"messages": {
"one": {
"m1": { "sender": "Mchen", "message": "foo" },
"m2": { ... },
"m3": { ... }
},
"two": { ... },
"three": { ... }
}

}

使数据可扩展

在许多场景下,我们有双向查询数据的需求。此时需要在数据结构中添加必要的冗余,以提高查询的效率。

例如,你需要设计一个聊天室的数据结构,该结构包含两个对象: user 和 room。两者是双向关系,user 可以属于多个room,room 可以包含多个user 。

{
"users": {
"Chen": { "name": "Mary Chen" },
"Rinchen": { "name": "Byambyn Rinchen" },
"Madi": { "name": "Hamadi Madi" }
},
"rooms": {
"room1": {
"name": "Alpha Tango",
"members": {
"user1": "mchen",
"user2": "brinchen",
"user3": "hamadi"
}
},
"room2": { ... },
"room3": { ... }
}
}

如上设计,当 user 需要查询自己属于哪个 room 时,该数据结构会遍历所有的 room,效率极低。更严重的是,如果 user 没有权限查看所有的 room,就不能实现需求。

正确的做法如下,在 user 下存入所属 room 的信息

{
"users": {
"Chen": {
"name": "Mary Chen",
// 在Mary的数据下,建立他所属 room 的索引。
"rooms": {
"room1": true,
"room2": true
}
},
...
},
"rooms": { ... }
}

只需要读取/users/Chen/rooms/$room_id,看它是否为 null 就可以了。

但这样做需要注意,如果 user 和 room 的关系发生变化,就需要更新两个地方的关系数据。

野狗新手?
立即注册,为你提供安全可靠的实时通信云服务。
没找到需要的文档?
你可以提交工单反馈 或 阅读常见问题