文档数据库简介与RavenDB使用示例

文档数据库是一种用于存储、检索和管理文档的数据存储系统。与传统的关系型数据库不同,文档数据库以文档为中心,每个文档可以包含复杂的结构,如嵌套对象、数组等。这种数据库适合存储半结构化或非结构化数据,如JSON、XML等格式的数据。RavenDB是一个开源的文档数据库,它提供了丰富的功能,包括数据索引、分区(sharding)等,以满足不同场景下的数据存储需求。

文档数据库的基本概念

在没有使用过文档数据库的情况下,最简单的理解方式是将其想象为将对象序列化后存储在硬盘上,应用程序所在的位置上。如果使用键或者任何最常用的查找方法来存储,那么检索整个对象将变得非常简单,无需映射到SQL数据库中的列和行。处理进一步的查找方式、并发等问题会更加困难,因此产生了文档数据库。存储的文档不一定需要是序列化的对象(可以独立于对象存储任意文档),但那可能是最常见的使用方式。请记住,这是一种完全不同的数据存储方式,所以不应该总是像处理SQL数据库那样来处理它。

RavenDB的简单示例

下面是一个简单的示例,展示了如何在RavenDB中存储两个任意的POCO对象,查询它们并将一些信息打印到屏幕上。在这个示例中,RavenDB服务器和客户端位于同一台机器上,但这不是必须的(接下来会有更多相关内容)。注意,不需要创建表,不需要将列和类映射到表,也不需要创建任何存储过程。Company类甚至没有标记为可序列化的——它就是可以工作。

还请注意,创建DocumentStore对象应该被视为昂贵的操作,类似于在NHibernate中创建会话工厂。目前还不是这样,但有未来的工作计划可能会改变这一点。

服务器和客户端

启动服务器并运行上述示例时,将看到服务器上的输出与上述类似(使用log4net,因此控制台日志可以关闭或重定向到文件,如果需要的话)。这里有很多有趣的事情。首先,注意它不是提交两个命令,而是将它们批量处理并一次性提交给SaveChanges()调用。其次,在批量操作之后,它开始处理适用于已保存文档的索引,并能够查询并返回这些文档。

除了上面展示的客户端/服务器方法之外,如果不需要分布式架构,还可以将服务器功能直接嵌入到应用程序中。

基于浏览器的管理工具

一旦Raven服务器运行,可以通过浏览器访问它以检查其内容、索引并查看文档。甚至可以使用浏览器编辑文档和索引定义。

索引和性能

可能已经注意到了,在上述简单示例中的查询方法调用了"WaitForNonStaleResults"。当设计使用索引的系统时,可以采取几种方法:

  • 在数据更改时让客户端等待,同时更新索引
  • 如果索引不是最新的(陈旧的),在读取索引数据时让客户端等待
  • 在更新或读取时不让客户端等待,只是让客户端知道数据是否陈旧

RavenDB出于性能原因采取了第三种选择,但如果想让它等待,可以使用WaitForNonStaleResults方法。如果没有包含该方法,并且在插入和读取之间发生了任何其他操作(因为索引更新时间往往在几十毫秒内),它仍然可以工作。通常,获取陈旧数据,同时索引更新,并在下一次视图或查询中获取更新的数据,这样更足够且成本更低。

使用LINQ添加新索引

可以使用Web UI或以编程方式创建或编辑索引。这里将展示如何使用Web UI添加新索引,并使用该索引进行查询。

首先,使用LINQ语法创建索引:

// 示例代码 var index = new IndexCreation.CreateIndexDefinition<Company>() { Map = companies => from company in companies select new { company.Name, company.Employees } }; index.Execute(_documentStore);

然后,使用Lucene语法编写一个使用该索引的查询:

// 示例代码 var companies = _documentStore.DatabaseCommands.Query<Company>("CompanyIndex", new IndexQuery { Query = "Employees:5", PageSize = 10 }).ToList();

服务器将识别索引的存在,并使用Lucene通过它获取更小的结果集,而不是扫描所有项目。

分片(Sharding)

Raven DB还支持分片,即将数据分区到多台服务器上。例如,如果知道许多公司分布在多个区域,并且希望某些区域在一台服务器上,其他区域在另一台服务器上,可以实现这一点。分片的设计基于Hibernate Shards,所以如果熟悉它,会注意到一些相似之处。

下面是一个使用分片的示例(包含在RavenDB源代码中的示例项目):

// 示例代码 public class CompanyShardingStrategy : IShardStrategy { public ShardAccessor GetShardAccessor() { return new ShardAccessor(new ShardAccessorOptions { ShardSelectionStrategy = new CompanyShardSelectionStrategy(), ShardAccessStrategy = new ParallelShardAccessStrategy() }); } }

使用分片时,必须想出规则来按分区划分数据。在这个示例中,将假设有2个分片,区域A的公司去分片1,区域B的公司去分片2。为了实现这一点,将创建一个具体实例,实现IShardStrategy,定义3部分的分片行为:

  • ShardSelectionStrategy是它如何知道将新项目放入哪个分片:
  • 分片访问策略控制它如何在多个分片上执行查询。这里使用了内置的并行方法,它将同时查询所有分片并返回结果。还使用了现有的解析策略,搜索所有分片。有关这些策略背后思想的更多信息,请参见Hibernate Shards文档。

使用.NET 4.0/VS2010特性实现的功能

ParallelShardAccessStrategy使用了.NET 4.0中的新Tasks功能。下面是同时查询所有分片的代码:

// 示例代码 var results = shardAccessor.Query<Company>(q => q .WaitForNonStaleResults() .Where(x => x.Name == "Company Name") ).ToList();

还有一个实现expando对象的代码,它允许动态访问JSON对象:

// 示例代码 dynamic company = new ExpandoObject(); company.Name = "New Company"; company.Employees = 50; _documentStore.Store((object)company);

查看源代码以获取更多示例和详细信息。

从这里开始

要运行这里显示的示例,请下载源代码zip文件,在VS 2010中打开并构建解决方案。运行Raven.Server以启动服务器,然后启动简单的客户端示例,取消注释初始代码,以便最初将数据插入数据库,以便用一些数据填充它。要运行分片示例,需要复制Raven.Server bin目录并更改其配置,以便它在不同的端口上监听,以便可以在同一台机器上同时运行两个服务器(或使用另一台机器)。第一次运行服务器时,如果它检测到没有访问端口的权限,它将授予权限,这将提示进行管理员访问。

产品中的功能远不止在这里展示的——要查看其余部分,请查看代码。源代码存储库在github上,网址为http://github.com/ravendb/ravendb——但当前的源代码和示例代码包含在文章中。如果想贡献,可以使用git获取所有代码,或者使用github在上述链接处提供的"下载源代码"按钮下载所有需要的文件。还会在github上找到一个问题列表,所以如果想跳进去并帮助解决一个小问题以熟悉使用git和VS 2010,那就去做吧。

另外,请参阅Oren的博客,它包括许多与Raven相关的帖子,因为它正在构建,提供了一些设计决策的见解等。

以下是在Windows机器上本地运行git的说明。

// 示例代码 git clone https://github.com/ravendb/ravendb.git cd ravendb git checkout develop

到目前为止,使用Git GUI对来说很有用(与命令行相比),即使在使用一些更复杂的场景,如创建和合并分支时也是如此。只是了解一下git分支的命令行指令很有帮助,这样就知道术语了,这与VSS/TFS/SVN非常不同。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485