MongoDB

最近试用 MongoDB。对于从关系型数据库入门的开发者来说,比较困惑的是表结构要怎样设计。没有哪一张表是一个孤岛,关系型数据库搞关系主要靠 Join。然后你会搜索怎样在 MongoDB 里做 Join,发现对应的 $lookup() 是 v3.2 才支持的。虽然那也已经是几年前的事了,但是你就比较困惑,v3.2 之前难道就不 Join 了。

不是一定要 Join 的。摆脱范式的束缚不正是使用 NoSQL 的初衷之一么。MongoDB 文档 Data Models 部分把 Embedded Data 和 References 两种 Document Structure 说明得比较清楚了。

Embedded Data 和 Nested JSON 是很对仗的。

Tabulator

Tabulator 是个用来创建数据表格的功能强大的 JS 库。

在它的 Examples 页面,有 Nested TablesNested Data Trees 两个例子。具体效果可打开链接查看,后台输入的数据如下:

Nested Tables

[
  {id:1, make:"Ford", model:"focus", reg:"P232 NJP", color:"white", serviceHistory:[
    {date:"01/02/2016", engineer:"Steve Boberson", actions:"Changed oli filter"},
    {date:"07/02/2017", engineer:"Martin Stevenson", actions:"Break light broken"},
  ]},
  {id:1, make:"BMW", model:"m3", reg:"W342 SEF", color:"red", serviceHistory:[
    {date:"22/05/2017", engineer:"Jimmy Brown", actions:"Aligned wheels"},
    {date:"11/02/2018", engineer:"Lotty Ferberson", actions:"Changed Oil"},
    {date:"04/04/2018", engineer:"Franco Martinez", actions:"Fixed Tracking"},
  ]}
]

Nested Data Trees

[
    {name:"Oli Bob", location:"United Kingdom", gender:"male", col:"red", dob:"14/04/1984", _children:[
        {name:"Mary May", location:"Germany", gender:"female", col:"blue", dob:"14/05/1982"},
        {name:"Christine Lobowski", location:"France", gender:"female", col:"green", dob:"22/05/1982"},
        {name:"Brendon Philips", location:"USA", gender:"male", col:"orange", dob:"01/08/1980", _children:[
            {name:"Margret Marmajuke", location:"Canada", gender:"female", col:"yellow", dob:"31/01/1999"},
            {name:"Frank Harbours", location:"Russia", gender:"male", col:"red", dob:"12/05/1966"},
        ]},
    ]},
    {name:"Jamie Newhart", location:"India", gender:"male", col:"green", dob:"14/05/1985"},
    {name:"Gemma Jane", location:"China", gender:"female", col:"red", dob:"22/05/1982", _children:[
        {name:"Emily Sykes", location:"South Korea", gender:"female", col:"maroon", dob:"11/11/1970"},
    ]},
    {name:"James Newman", location:"Japan", gender:"male", col:"red", dob:"22/03/1998"}
]

上面两个就是典型的 Nested JSON,直接以 Embedded structure 保存在 MongoDB 应该挺方便的

关系型数据库

这样的数据如果要保存在关系型数据库呢?比如 SQLite,省得另起一个数据库服务器。

表结构要怎样设计,是不是还得写循环去拼接出 Tabulator 可用的 Nested JSON?

JSON 也不是什么新鲜玩意,这个问题当然有人遇到有人处理了。用关键字搜索,SQL Server 和 SQLite 都有 JSON 相关的支持,相信其它的主流关系型数据库也有。

SQL Server 当然功能强大些,比如上面 Tabulator 的第一个例子,你可以把 1:N 的 N 这一侧的数据在 join 时转为 JSON,所以数据结构不需要变化,仍然是符合范式的。

SQLite 的 The JSON1 Extension 则似乎侧重于方便存取 JSON 格式的数据

还在学习中,不展开。

JSON1 Extension

安装 JSON1 Extension 需要……自己编译,这是个拦路虎。

DB Browser for SQLite 默认启用了 JSON1 Extension,可以先试试看。编程语言接口是否需要额外的支持还需要再调查。

JSON 数据类型也启用了,只是在界面中不显示,可以通过 SQL statement 直接使用。

重点是 json_each()json_tree() 两个函数,可以参考文档的例子。

SQLite 的文档有点单薄。

关系型数据库的 JSON 支持之前也扫到过,光读文档没什么感觉。这次有了实际的用例,才有了恍然大悟的感觉。

最近在思考什么是合适的编程学习方式,一些旧的思维模式需要调整,这是一个有启发的例子。