构建一个基于 Node.js 的表驱动存储容器应用(4)
 
- UID
- 1066743
|

构建一个基于 Node.js 的表驱动存储容器应用(4)
步骤 5. 分析主文件现在,您将实时创建一个基本的 CouchDB 数据库。Storeall 应用程序是一个通用的存储容器,它将通过使用 jTable 表来促使完成数据库的创建、读取、更新与删除(CRUD)操作,您可以在该容器中保存键值对。
了解 app.js 的关键部分从查看 app.js 文件开始。
Nano 如何访问 CouchDB 或 Cloudant如果处理 Bluemix 环境变量时返回一个证书对象,app.js 使用该对象的 URL 将 Nano 绑定到数据库。如果没有返回任何证书对象,app.js 知道代码位于本地 PC 上,因此它在端口 5984 上与 CouchDB 进行交互,并指示 Nano 在本地与数据库进行交互。
1
2
3
4
5
6
7
8
| if (creds!==undefined){
nano=require('nano')(creds.url)
} else {
nano = require('nano')('http://localhost:5984');
}
nano.db.create('storeall');
var db = nano.db.use('storeall');
|
让数据库对象对所有后端请求都变为可用每次发送请求访问一个页面时,都会传递 Nano 对象来支持与数据库的交互:
1
2
3
4
| app.use(function(req,res,next){
req.db = db;
next();
});
|
了解 index.js 的关键部分接下来将查看 routes/index.js 文件。
create 函数在 CRUD 操作中,create 函数负责将新的数据行插入到数据库中。在 NoSQL 术语中,一行就是一个文档。在使用 Nano 时,建立各个字段后就会发出插入调用,而这些字段基于由 jTable 插入函数收集到的数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| db.insert({itemname:itemname,itemvalue:itemvalue,itemremarks:itemremarks,itemdatecreated:
itemdatecreated,itemdatemodified:itemdatemodified, itemusage:itemusage, itemvisible:itemvisible,
crazy: true }, itemname,function(err, body, header) {
if (err) {
retObj.Result="ERROR";
retObj.Message="Could not create item or item already exists";
} else {
retObj.Result = "OK";
retObj.Record=body;
}
res.send(json.stringify(retObj));
});
});
|
Nano 插入函数使用一个 JSON 对象,其中包含要插入的字段,用作主键的字段(itemname),以及一个在插入操作返回后接收控制的回调函数。因为大多数 Node.js 调用都是异步的,所以必须传入这个回调函数,以便在操作完成时通过 Node 调用它。该回调函数有三个参数:
- 一个错误字符串,如果操作成功则不会定义
- 一个包含返回数据的 body 对象
- 一个包含头部的对象
如果插入调用成功,就会返回一个 JSON 对象给 jTable,其中 Result 字段的值被设置为 OK,而 Record 字段包含插入后的数据。如果调用失败,Result 将被设置为 ERROR,而 Message 字段中包含错误消息。
update 函数从根本上说,update 函数就是 insert 函数,但二者之间存在一处主页差别。所有更新都必须提供一个修订号,CouchDB 用它来实现并发性。每次进行更新时都会增加修订号的值。如果当另一用户尝试更新文档时它已被更新(即有人在文档被读取后访问和更新了它),那么修订号将从当前更新人的数字开始增加。现在的修订号已经过时,CouchDB 的更新操作就会失败。如果出现这种情况,必须进行再次读取和数据调整。
下面的调用要求 CouchDB 基于 itemname 主键和修订号插入文档:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| db.insert({itemname:itemname,itemvalue:itemvalue,itemremarks:itemremarks,itemdatecreated:
itemdatecreated,itemdatemodified:itemdatemodified, itemexpiration:itemexpiration, itemusage:
itemusage, itemvisible:itemvisible, crazy: true, _rev:rev }, itemname,function(err, body, header) {
if (err) {
retObj.Result="ERROR";
retObj.Message="Error updating item...it was possibly updated by another user.
Re-read it";
} else {
retObj.Result = "OK";
retObj.Record=body;
}
res.send(json.stringify(retObj));
});
} else {
retObj.Result="ERROR";
retObj.Message="Item not found";
res.send(json.stringify(retObj));
}
});
});
|
调用依赖于 CouchDB 检测所有修订冲突。如果插入成功,那么 CouchDB 将会在 body 对象中返回新的修订号。这样 CouchDB 本身就不会进行更新。每次更新都是使用一个新的修订号插入一个新文档。
list 函数list 函数基本上与 read 函数相同,负责提供数据显示在 jTable 表中。list 函数通过查询字符串接收到以下信息:
- 指定主键列排序方法(升序或降序)的参数:jtSorting
- 开始显示文档的索引位置:jtPageStartIndex
- 每页显示的内容项数量:jtPageSize
这段代码将这些参数映射为 Nano list 函数(与应用程序的 list 函数不同)理解的值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| router.post('/itemlist', function(req, res) {
var sorting_desceding = true;
//determine the sort order from the querystring
if (req.query.jtSorting !== undefined){
//Two possible values are ASC and DESC. If the last three characters of a value are ESC then
//we assume they passed DESC else default to ASC
sorting_descending = (req.query.jtSorting.substring(req.query.jtSorting.length-3)==='ESC');
}
var db = req.db
//jtPageSize = number of items to display on the table
//jtStartIndex is the first item to display on the table, we tell cloudant to skip
//x # of items so the start index
//can be the index of the first item to display
, params = {include_docs: true, skip: req.query.jtStartIndex, limit:
req.query.jtPageSize, descending: sorting_descending};
db.list(params, function(error,body,headers) {
var docs = [];
var row;
for (row in body.rows){
//the list functions displays all the databases along with the documents
//so we extract the documents and send them to jtable
//console.log('row text '+body.rows[row].id + ' and row=' + row);
docs[row]=body.rows[row].doc;
}
var json_obj = {};
json_obj.Result = "OK";
json_obj.Records = docs;
//adjust all the parameter that allows us to paginate the table
json_obj.TotalRecordCount=body.total_rows;
res.send(json.stringify(json_obj));
});
});
|
告诉 Nano list 函数使用 include_docs 参数返回文档。默认情况下,CouchDB 不返回文档,只返回文档主键。
因此,将这些文档从 CouchDB 返回的数组中提取出来,然后把它们分派给 jTable。也可以在数据库中包含文档的总数,以便 jTable 进行分页。
|
|
|
|
|
|