关于黑客新闻的讨论这是 Jao-ke Chin-Lee 和 Jed Estep 的客座帖子,他们目前是 10gen 的实习生。今年夏天,他们的任务是为 MongoDB 构建 Rust 驱动程序。今天我们开源 Mongo 的 alpha 版本
讨论黑客新闻
这是 Jao-ke Chin-Lee 和 Jed Estep 的客座文章,他们目前是 10gen 的实习生。今年夏天,他们的任务是为 MongoDB 构建 Rust 驱动程序。
今天,我们开源了 Rust 编程语言的 MongoDB 驱动程序的 alpha 版本。这是在 Rust 社区的帮助下两个月的工作成果,我们很高兴能够分享我们的初始版本。我们期待来自 Rust 和 MongoDB 社区的反馈。
Rust 是一种多范式、面向系统的语言,目前 Mozilla 正在开发中。它具有命令式、函数式和面向对象语言的元素,还包括雄心勃勃的新功能,例如允许智能自动内存管理和并发的仿射类型。其强大的类型和内存安全功能在编译时运行,并且仍然保持低级语言的典型性能。随着该语言的不断发展,用本机 Rust 编写的 MongoDB 驱动程序的可用性将 Rust 和 MongoDB 暴露给新的受众。
该驱动程序已获得 Apache 许可,并且纯粹用 Rust 实现,不依赖于任何 C 扩展或库(md5 的嵌入式副本除外,当 Rust 提供本机实现时可以将其删除)。
使用当前 MongoDB 驱动程序的用户会感觉很熟悉该驱动程序。基本 BSON 类型(例如字符串、数字和对象)具有基于 Rust 代数数据类型的内置内部表示。用户还可以实现一个特征(类似于 Haskell 类型类,类似于 Java 接口),该特征允许他们将其代码库的本机类型视为 BSON 的本机类型。
一旦用户的数据被格式化,就可以通过熟悉的对象(如 Collection、DB、Cursor 和 Client)与数据库进行交互。这些对象与其他语言中的对应对象具有相似的 API,目前在 Rust 抽象的框架中提供 CRUD、索引以及管理功能,并平衡 Rust 静态保证的理念与 MongoDB 的灵活性。下面提供了一个小例子。
首先我们需要导入 mongo 库和我们将要使用的类。
extern mod mongo; use mongo::client::*; use mongo::util::*; use mongo::coll::*; use mongo::db::*;
为了与 Mongo 服务器连接,我们首先创建一个客户端。
let client = @Client::new();
要连接到在本地主机端口 27017 (MONGO_DEFAULT_PORT) 上运行的未复制、未分片的服务器,我们使用 connect 方法:
match client.connect(~"127.0.0.1", MONGO_DEFAULT_PORT) { Ok(_) => (), Err(e) => fail!(e.to_str()), }
我们在数据库“rust_ex”中创建一个名为“capped”的上限集合,方法是首先创建“rust_ex”数据库的句柄(可能为空,也可能不为空),然后使用指定上限集合大小的参数调用 create_collection (必须不存在)。
let db = DB::new(~"rust_ex", client); match db.create_collection(~"capped", None, Some(~[CAPPED(100000), MAX_DOCS(20)])) { Ok(_) => (), Err(e) => fail!(e.to_str()), };
现在我们创建一个tailable游标来提取“a”字段的值可以被5整除的文档,并投影到“msg”字段上。
let coll = Collection::new(~"rust_ex", ~"capped", client); let mut cursor = match coll.find( Some(SpecNotation(~"{ 'a':{'$mod':[5,0]} }")), Some(SpecNotation(~"{ 'msg':1 }")), None) { Ok(c) => c, // JSON-formatted strings are automatically converted to BSON Err(e) => fail!(e.to_str()), }; cursor.add_flags(~[CUR_TAILABLE, AWAIT_DATA]);
然后我们生成一个线程来填充上限集合。请注意,对于第一次插入,我们指定 None 作为 writeconcern,这表示默认值 1,而对于后续插入,我们将 writeconcern 指定为 Journaled。
coll.insert(~"{ 'a':0, 'msg':'first insert' }", None); let n = 50; do spawn { let tmp_client = @Client::new(); tmp_client.connect(~"127.0.0.1", MONGO_DEFAULT_PORT); let coll = Collection::new(~"rust_ex", ~"capped", tmp_client); let mut i = 1; for n.times { match coll.insert( fmt!("{ 'a':%?, 'msg':'insert no. %?' }", i, i), Some(~[JOURNAL(true)])) { Ok(_) => (), Err(e) => println(fmt!("%s", e.to_str())), }; i += 1; } tmp_client.disconnect(); }
同时,在主线程中,我们迭代从 tailable 游标返回的结果。
for 25.times { let mut p = cursor.next(); while p.is_none() && !cursor.is_dead() { p = cursor.next(); } if cursor.is_dead() { break; } println(fmt!("read %?", p.unwrap().to_str())); }
最后,我们断开客户端连接。此客户端可以重复使用以连接其他服务器。
match client.disconnect() { Ok(_) => (), Err(e) => fail!(e.to_str()), }
有关类似示例,包括将用户实现的结构插入数据库并从数据库读取的工作示例,请参阅示例。
请在 GitHub 存储库中找到更多示例以及我们鼓励您查看和使用的源代码。我们还有可用的文档。请记住,该驱动程序目前仅在 Rust 0.7 版本上构建,并且不适用于其他版本的 Rust。我们欢迎任何反馈和贡献;创建问题或提交拉取请求!
MongoDB Rust 驱动程序由 Jao-ke Chin-Lee 和 Jed Estep 开发,他们目前是 10gen 的实习生。我们被 Rust 的创新以及连接 Rust 和 MongoDB 社区的想法所吸引。
非常感谢 IRC 上的 Rust 社区和 rust-dev 对 Rust 的指导,并开发了如此令人兴奋的语言。特别感谢 10gen 接待我们实习生,Stacy Ferranti 和 Ian Whalen 管理实习计划,感谢我们的导师 Tyler Brock 和 Andrew Morrow 在整个项目过程中提供的帮助和支持。
译文地址:介绍 Rust Progra 的 MongoDB 驱动程序,感谢原作者分享。