因为接受的答案只提供(良好的)其他资源的链接,所以我想我会分享我编写webdb的经验,这是一个用于浏览器的小型实验数据库。我还邀请您阅读源代码。它很小。您应该能够通读它并在几个小时内基本了解它在做什么。警告:我在这方面是一个 n00b,自从写了它之后,我学到了很多关于它的知识,并且发现我做错了一些事情。不过,它可以帮助您入门。
基础知识:BTree
我开始调整 AVL 树以满足我的需要。AVL 树是一种自平衡二叉搜索树。您将键K和相关数据(如果有)存储在一个节点中,然后将所有项目存储key < K
在左子树中的节点中,并将所有项目存储key > K
在右子树中。如果要支持非唯一键,可以使用数组来存储数据项。
这棵树将为您提供基础知识:创建、更新、删除以及一种通过键快速获取项目的方法,或者键 < x 或键在 x 和 y 之间的所有项目等。它可以作为我们表的索引.
架构
作为下一步,我编写了让客户端代码定义模式的代码。诸如此类的方法createTable()
。模式通常与 SQL 相关联,但即使是非 SQL 类型也有模式;他们通常要求您标记 ID 字段和您要搜索的任何其他字段。您可以使您的架构随心所欲,但您通常希望至少对哪些列用作主键以及哪些字段将被频繁搜索并需要索引进行建模。
创建数据结构来存储表
我决定使用我在第一步中创建的树来存储我的项目。这些是简单的 JS 对象。在定义了哪个字段包含 PK 之后,我可以简单地将项目插入到树中,使用该字段的值作为键。这使我可以按 ID(范围)快速查找。
接下来,我为需要索引的每一列添加了另一棵树。在这些树中,我没有存储完整的记录,而只存储了密钥。因此,要按姓氏获取客户,我将首先使用姓氏索引来获取 ID,然后使用主键索引来获取实际记录。我不只是存储(引用)实际对象的原因是因为它使集合操作更简单一些(见下一步)
查询
现在我们有了一个包含 PK 和搜索字段索引的表,我们可以实现查询。我没有把它走得太远,因为它很快就会变得复杂,但是你可以通过一些基础知识来获得一些不错的功能。WebDB 不实现连接;所有查询仅对单个表进行操作。但是一旦你理解了这一点,你就会看到一条非常清晰(虽然漫长而曲折)的路径来进行连接和其他复杂的事情。
在 WebDB 中,要让所有客户使用firstName = 'John'
和city = 'New York'
(假设这是两个搜索字段),您可以编写如下内容:
var webDb = ...
var johnsFromNY = webDb.customers.get({
firstName: 'John',
city: 'New York'
})
为了解决这个问题,我们首先进行两次查找:我们获取名为“John”的所有客户 ID 的集合X ,以及来自纽约的所有客户 ID的集合Y。然后,我们对这两个集合执行交集,以获取所有来自纽约的名为“John” AND的客户的 ID。然后,我们遍历我们的一组结果 ID,获取每个 ID 的实际记录并将其添加到结果数组中。
使用联合和交集等集合运算符,我们可以执行AND和OR搜索。我只实现了AND。
进行联接(我认为)涉及在内存中创建临时表,然后在查询运行时使用联接结果填充它们,然后将查询条件应用于临时表。我从来没有到过那里。接下来我尝试了一些同步逻辑,但这太雄心勃勃了,从那里开始走下坡路:)