What is Oracle bone inscriptions? A bunch of people. All our products are just the ideas in these people's minds-the ideas that people put into computers and tested, which proved to be the best ideas for databases or programming languages. - Larry Ellision [T1】 T3]
在本章中,我们将探讨以下主题:
- 蒙戈布贝壳
- Node.js 的 MongoDB 本机驱动程序
- MongoDB on Heroku with MongoLab
- 留言板:MongoDB 版本
MongoDB 是一个 NoSQL 文档存储数据库。它具有可扩展性和高性能。它没有模式,所以所有的逻辑和关系都在应用层实现。你可以使用像水线或者猫鼬这样的 ODM。MongoDB 使用 JavaScript 接口,完成了浏览器、服务器、数据库层的全栈 JavaScript 栈拼图。有了 MongoDB,我们可以对所有三层使用一种语言。开始使用 MongoDB 最简单的方法是使用它的 shell,也就是 REPL (read-eval-print-loop)。
如果您还没有安装,请从 mongodb.org/downloads 安装最新版本的 MongoDB。更多说明,请参考第二章中的数据库:MongoDB 部分。您可能需要按照说明创建一个数据文件夹。
现在,从解压归档文件的文件夹中,使用以下命令启动mongod服务:
$ ./bin/mongod
在localhost:28017时,您应该能够在您的终端和浏览器中看到信息。
对于 MongoDB shell,或mongo,在新的终端窗口中启动(重要!),并在同一文件夹中执行以下命令:
$ ./bin/mongo
根据您的 MongoDB shell 版本,您应该会看到类似这样的内容:
MongoDB shell version: 2.0.6
connecting to: test
要测试数据库,使用类似 JavaScript 的界面和命令save和find:
> db.test.save( { a: 1 } )
> db.test.find()
更详细的分步说明可以在数据库中找到:第 2 章的的 MongoDB 部分。
其他一些有用的 MongoDB shell 命令来自 MongoDB 和 mongose cheat sheet(https://gum.co/mongodb/git-874e6fb4):
> show dbs:显示服务器上的数据库> use DB_NAME:选择数据库DB_NAME> show collections:显示所选数据库中的收藏> db.COLLECTION_NAME.find():对名称为 COLLECTION_NAME 的集合执行查找查询,查找任何项目> db.COLLECTION_NAME.find({"_id": ObjectId("549d9a3081d0f07866fdaac6")}):对 COLLECTION_NAME 名称的集合执行查找查询,查找 ID 为 549d9a3081d0f07866fdaac6 的项目> db.COLLECTION_NAME.find({"email": /gmail/}):对 COLLECTION_NAME 名称的集合执行查找查询,查找邮件属性与/gmail匹配的项目> db.COLLECTION_NAME.update(QUERY_OBJECT, SET_OBJECT):对 COLLECTION_NAME 名称的集合执行更新查询,更新 QUERY_OBJECT 与 SET_OBJECT 匹配的项目> db.COLLECTION_NAME.remove(QUERY_OBJECT):对 COLLECTION_NAME 集合中符合 QUERY_OBJECT 条件的项目进行删除查询> db.COLLECTION_NAME.insert(OBJECT):将对象添加到名称为集合名称的集合中
因此,从一个新的 shell 会话开始,您可以执行以下命令来创建、更改和删除文档:
> help
> show dbs
> use board
> show collections
> db.messages.remove();
> var a = db.messages.findOne();
> printjson(a);
> a.message = "hi";
> a.name = "John";
> db.messages.save(a);
> db.messages.find({});
> db.messages.update({name: "John"},{$set: {message: "bye"}});
> db.messages.find({name: "John"});
> db.messages.remove({name: "John"});
你可以下载 MongoDB 和 Mongoose cheatsheet 作为 PDF ( https://gumroad.com/l/mongodb/fsjs-CB07C579 #)或者在 https://github.com/mongodb/node-mongodb-native/#data-types 在线查看。
MongoDB 交互 shell 的完整概述可以在 mongodb.org 上找到:概述——MongoDB 交互 Shell ( https://docs.mongodb.org/manual/tutorial/getting-started-with-the-mongo-shell/ )。
二进制 JSON 或 BSON 是 MongoDB 使用的一种特殊数据类型。它在符号上类似于 JSON,但是支持更多更复杂的数据类型,比如 buffer 或 date。
关于 BSON 有一点需要注意:MongoDB 中的 ObjectID 相当于 MongoDB Native Node.js 驱动程序中的 ObjectId(即,确保使用正确的大小写)。否则你会得到一个错误。更多关于类型:MongoDB 中的 ObjectId(http://www.mongodb.org/display/DOCS/Object+IDs)vsMongoDB 原生 Node 中的数据类型。js 干燥机 ( https://github.com/mongodb/node-mongodb-native/#data-types )。带有mongodb.ObjectID() : collection.findOne({_id: new ObjectID(idString)}, console.log) // ok的 Node.js 代码示例。另一方面,在 MongoDB shell 中,我们使用了:db.messages.findOne({_id:ObjectId(idStr)});。
引导您完成实施并演示项目的补充视频: http://bit.ly/1QnqZSk 。
我们将使用 MongoDB 的 Node.js 本地驱动程序( https://github.com/christkv/node-mongodb-native )从 Node.js 应用访问 MongoDB。完整文档也可在 http://mongodb.github.com/node-mongodb-native/api-generated/db.html 获取。
要为 Node.js 安装 MongoDB 本机驱动程序,请使用:
$ npm install mongodb
更多详情请见 http://www.mongodb.org/display/DOCS/node.JS 。
不要忘记在package.json文件中包含依赖关系:
{
"name": "node-example",
"version": "0.0.1",
"dependencies": {
"mongodb":"",
...
},
"engines": {
"node": ">=0.6.x"
}
}
或者,对于您自己的开发,您可以使用其他映射器,它们是本地驱动程序的扩展:
- Mongoskin(
https://github.com/guileen/node-mongoskin):node-MongoDB-native 的未来层 - 猫鼬 (
http://mongoosejs.com/):一个异步 JavaScript 驱动程序,可选支持建模 - 蒙古 (
https://github.com/masylum/mongolia):一个轻量级的 MongoDB ORM/driver 包装器 - 蒙克 (
https://github.com/Automattic/monk):一个微小的层,为 Node.js 中 MongoDB 的使用提供了简单但实质性的可用性改进
这个小例子将测试我们是否可以从 Node.js 脚本连接到本地 MongoDB 实例。
在我们安装了库之后,我们可以在我们的app.js文件中包含mongodb库:
var util = require(’util’)
var mongodb = require (’mongodb’)
这是建立到 MongoDB 服务器的连接的方法之一,其中 DB 变量将保存对指定主机和端口上的数据库的引用:
var Db = mongodb.Db
var Connection = mongodb.Connection
var Server = mongodb.Server
var host = ’127.0.0.1’
var port = 27017
var db=new Db (’test’, new Server(host,port, {}))
要实际打开一个连接:
db.open(function(error, connection){
// Do something with the database here
db.close()
})
为了检查我们是否有连接,我们需要处理error。同样,让我们用db.admin()获取管理对象,用listDatabases()获取数据库列表:
var db=new Db (’test’, new Server(host, port, {}))
db.open(function(error, connection){
console.log(’error: ’, error)
var adminDb = db.admin()
adminDb.listDatabases(function(error, dbs) {
console.log(’error: ’, error)
console.log(’databases: ’, dbs.databases)
db.close()
})
})
这段代码片段可在https://github.com/mongodb/node-mongodb- native/#data-types获得。如果我们运行它,它应该在终端中输出“connected”。当你有疑问并且需要检查一个对象的属性时,在util模块中有一个有用的方法:
console.log(util.inspect(db))
现在,您可能希望在云中设置数据库,并从 Node.js 脚本测试连接。
引导您完成实施并演示项目的补充视频: http://bit.ly/1Qnr8Fn 。
在您使显示“已连接”的应用在本地工作之后,是时候稍微修改它并将其作为服务部署到平台上了(例如 Heroku)。
我们推荐使用 MongoLab 附加组件( https://elements.heroku.com/addons/mongolab )。MongoLab 插件提供了一个基于浏览器的 GUI 来查找和操作数据和集合。更多信息请访问 https://elements.heroku.com/addons/mongolab#docs 。
请注意,即使您选择了免费版本,也可能需要提供您的信用卡信息才能使用 MongoLab。不过,你不应该被起诉。
为了连接到数据库服务器,有一个数据库连接 URL(又名 MongoLab URL/URI),这是一种传输所有必要信息的方法,以便在一个字符串中连接到数据库。
数据库连接字符串MONGOLAB_URI具有以下格式:
mongodb://user:pass@server_NAME.mongolab.com:PORT/db_name
您可以从 Heroku 网站复制 MongoLab URL 字符串(并对其进行硬编码),或者从 Node.js process.env对象获取字符串:
process.env.MONGOLAB_URI
或者
var connectionUri = url.parse(process.env.MONGOLAB_URI)
全局对象进程通过process.env访问环境变量。这些变量通常用于传递数据库主机名和端口、密码、API 键、端口号以及其他不应该硬编码到主逻辑中的系统信息。
为了让我们的代码在本地和 Heroku 上都能工作,我们可以使用逻辑 OR 操作符||并在环境变量未定义的情况下分配一个本地主机和端口:
var port = process.env.PORT || 1337
var dbConnUrl = process.env.MONGOLAB_URI ||
’mongodb://127.0.0.1:27017/test’
这里是我们更新的跨环境就绪app.js文件( https://github.com/azat-co/fullstack-javascript/tree/master/10-db-connect-heroku )。我添加了一个方法来获取集合列表listCollections,而不是获取数据库列表(我们现在在 MongoLab 中只有一个数据库):
var util = require(’util’)
var url = require(’url’)
var client = require (’mongodb’).MongoClient
var dbConnUrl = process.env.MONGOLAB_URI ||
’mongodb://127.0.0.1:27017/test’
console.log(’db server: ’, dbConnUrl)
client.connect(dbConnUrl, {}, function(error, db){
console.log(’error: ’, error)
db.listCollections().toArray(function(err, collections) {
console.log(’error: ’, error)
console.log(’collections: ’, collections)
db.close()
})
})
通过添加MONGOLAB_URI对app.js进行修改后,我们现在可以初始化 Git 存储库,创建一个 Heroku 应用,向其中添加 MongoLab 附加组件,并使用 Git 部署该应用。
利用与前面示例中相同的步骤创建一个新的 git 存储库:
$ git init
$ git add .
$ git commit -am ’initial commit’
创建雪松栈 Heroku 应用:
$ heroku create
如果一切顺利,你应该可以看到一条消息,告诉你新的 Heroku 应用名称(和网址)以及一条消息,远程已被添加。在您的本地 git 中拥有 remote 是至关重要的;您可以随时通过以下方式查看遥控器列表:
$ git remote show
要在现有的 Heroku 应用上安装免费的 MongoLab(加载项基于每个应用),请使用:
$ heroku addons:create mongolab:sandbox
或者使用您的 Heroku 凭证登录 Heroku ( https://elements.heroku.com/addons/mongolab ),并为特定的 Heroku 应用选择 MongoLab Free(如果您知道该应用的名称)。
项目文件夹需要有Procfile和package.json。你可以从 https://github.com/azat-co/fullstack-javascript/tree/master/10-db-connect-heroku 中复制它们。
现在,您可以通过以下方式将代码推送到 Heroku:
$ git push heroku master
享受应该告诉您部署成功的日志。现在查看以下命令的输出:
$ heroku logs
结果将是这样的:
2015-12-01T12:34:51.438633+00:00 app[web.1]: db server: mongodb://heroku_cxgh54g6:9d76gspc45v899i44sm6bn790c@ds035617.mongolab.com:34457/heroku_cxgh54g6
2015-12-01T12:34:53.264530+00:00 app[web.1]: error: null
2015-12-01T12:34:53.236398+00:00 app[web.1]: error: null
2015-12-01T12:34:53.271775+00:00 app[web.1]: collections: [ { name: ’system.indexes’, options: {} },
2015-12-01T12:34:53.271778+00:00 app[web.1]: { name: ’test’, options: { autoIndexId: true } } ]
如果您让app.js和修改过的app.js文件工作,让我们通过添加一个 HTTP 服务器来增强,这样‘已连接’消息将显示在浏览器中,而不是终端窗口中。为此,我们将把服务器对象实例化封装在一个数据库连接回调中(file 11-d b-server/app . js athttps://github.com/azat-co/fullstack-javascript/blob/master/11-db/app.js)。
引导您完成实施并演示项目的补充视频: http://bit.ly/1Qnrmwr 。
var util = require(’util’)
var url = require(’url’)
var http = require(’http’)
var mongodb = require (’mongodb’)
var client = require (’mongodb’).MongoClient
var port = process.env.PORT || 1337
var dbConnUrl = process.env.MONGOLAB_URI || ’mongodb://@127.0.0.1:27017/test’
client.connect(dbConnUrl, {}, function(error, db) {
console.log(’error: ’, error)
db.listCollections().toArray(function(error, collections) {
console.log(’error: ’, error)
console.log(’collections: ’, collections)
var server = http.createServer(function (request, response) { // Creates server
response.writeHead(200, {’Content-Type’: ’text/plain’}) // Sets the right header and status code
response.end(util.inspect(collections)) // Outputs string with line end symbol
})
server.listen(port, function() {
console.log(’Server is running at %s:%s ’, server.address().address, server.address().port) // Sets port and IP address of the server
})
db.close()
})
})
最终 Heroku 部署就绪项目位于 https://github.com/azat-co/fullstack-javascript/tree/master/11-db-serverunder 。
部署完成后,您应该能够打开 Heroku 提供的 URL 并查看收藏列表。如果它是一个新创建的应用,数据库为空,则不会有收藏。您可以使用 Heroku 中的 MongoLab web 界面创建一个集合。
关于原生 MongoDB 驱动程序的更多信息,请查看 http://mongodb.github.io/node-mongodb-native/api-articles/nodekoarticle1.html
引导您完成实施并演示项目的补充视频: http://bit.ly/1QnsfoE .
我们应该已经为编写 Node.js 应用做好了一切准备,它既可以在本地运行,也可以在 Heroku 上运行。源代码可在 https://github.com/azat-co/fullstack-javascript/tree/master/12-board-api-mongonder 获得。应用的结构很简单:
/12-board-api-mongo
-web.js
-Procfile
-package.json
这就是web.js的样子;首先,我们包括我们的图书馆:
var http = require(’http’)
var util = require(’util’)
var querystring = require(’querystring’)
var client = require(’mongodb’).MongoClient
然后输出一个连接 MongoDB 的神奇字符串:
var uri = process.env.MONGOLAB_URI || ’mongodb://@127.0.0.1:27017/messages’
注意,URI/URL 格式包含可选的数据库名称,我们的集合将存储在其中。请随意将其更改为其他名称:例如,“rpjs”或“test”。
我们将所有逻辑以回调函数的形式放在开放连接中:
client.connect(uri, function(error, db) {
if (error) return console.error(error)
我们用下面的语句获取集合:
var collection = db.collection(’messages’)
现在,我们可以实例化服务器并设置逻辑来处理我们的端点/路由。我们需要在 GET /messages/list.json上获取文档:
var app = http.createServer( function (request, response) {
if (request.method === ’GET’ && request.url === ’/messages/list.json’) {
collection.find().toArray(function(error,results) {
response.writeHead(200,{ ’Content-Type’: ’text/plain’})
console.dir(results)
response.end(JSON.stringify(results))
})
在帖子/messages/create.json上,我们插入了文档:
} else if (request.method === ’POST’ && request.url === ’/messages/create.json’) {
request.on(’data’, function(data) {
collection.insert(querystring.parse(data.toString(’utf-8’)), {safe:true}, function(error, obj) {
if (error) throw error
response.end(JSON.stringify(obj))
})
})
} else {
如果客户端请求与上述任何条件都不匹配,就会显示这一信息。当我们试图去http://localhost:1337而不是http://localhost:1337/messages/list.json时,这是一个很好的提醒:
response.end(’Supported endpoints: \n/messages/list.json\n/messages/create.json’)
}
})
var port = process.env.PORT || 1337
app.listen(port)
})
Note
我们不必在集合/实体名称后使用额外的单词;也就是说,对于所有的 HTTP 方法,比如 GET、POST、PUT、DELETE,只使用/messages,而不是/messages/list.json和/messages/create.json,是非常好的。如果您在应用代码中更改它们,请确保使用更新的 CURL 命令和前端代码。
要通过 CURL 终端命令运行测试:
$ curl http://localhost:5000/messages/list.json
或者在http://locahost:1337/messages/list.json位置打开浏览器。
它应该会给你一个空数组:[],没问题。然后发布一条新消息:
$ curl -d "username=BOB&message=test" http://localhost:5000/messages/create.json
现在我们必须看到一个包含新创建元素的 ObjectID 的响应,例如:[{"username":"BOB","message":"test","_id":"51edcad45862430000000001"}]。您的 ObjectId 可能有所不同。
如果在本地一切正常,尝试将其部署到 Heroku。
要在 Heroku 上测试应用,您可以使用相同的 CURL 命令( http://curl.haxx.se/docs/manpage.html ),用您独特的 Heroku 应用的主机/URL 替换http://localhost/ or “ http://127.0.0.1 “:
$ curlhttp://your-app-name.herokuapp.com/messages/list.jsonT3】
$ curl -d "username=BOB&message=test"
T2http://your-app-name.herokuapp.com/messages/create.json
也可以通过 Mongo shell: $ mongo终端命令,然后是use twitter-clone和db.messages.find()来仔细检查数据库;或通过 MongoHub ( https://github.com/bububa/MongoHub-Mac )、mongoui ( https://github.com/azat-co/mongoui )、mongo-express( https://github.com/andzdroid/mongo-express )或在 MongoLab 的情况下通过其可在 heroku.com 网站访问的网络界面。
如果你想用另一个域名代替 http://your-app-name.herokuapp.com ,你需要做两件事:
Tell Heroku your domain name: $ heroku domains:add www.your-domain-name.com Add the CNAME DNS record in your DNS manager to point to http://your-app-name.herokuapp.com .
有关自定义域名的更多信息,请访问 devcenter.heroku.com/articles/custom-domains
提示为了更有效地开发,我们应该尽可能地自动化;也就是说,使用测试代替 CURL 命令。在奖励章节中有一篇关于 Mocha 库的文章,与superagent或request库一起,为这类任务节省了时间。
在本章中,我们已经介绍了 MongoDB 数据库及其 shell。MongoDB 使用 JSON 的扩展版本,称为 BSON。然后我们用原生 MongoDB 驱动切换到 Node.js。许多其他 MongoDB Node.js 库依赖于原生驱动程序,并在其上构建。正因如此,知道就好。为了在 Heroku 上使用 MongoDB,我们使用了 MongoLab 插件(神奇的MONGOLAB_URI)。最后,我们使用获得的知识为留言板应用添加持久性。