# 14數據庫
### MongoDB
### 問題
你需要與一個 MongoDB 數據庫連接的接口。
### 解決方案
#### 對于 Node.js
##### 安裝
-
如果你的計算機中還沒有 [MongoDB](http://www.mongodb.org/display/DOCS/Quickstart) ,需要安裝。
-
[安裝本地 MongoDB 模塊](https://github.com/christkv/node-mongodb-native)。
##### 保存記錄
~~~
mongo = require 'mongodb'
?
server = new mongo.Server "127.0.0.1", 27017, {}
?
client = new mongo.Db 'test', server, {w:1}
?
# save() updates existing records or inserts new ones as needed
?
exampleSave = (dbErr, collection) ->
console.log "Unable to access database: #{dbErr}" if dbErr
collection.save { _id: "my_favorite_latte", flavor: "honeysuckle" }, (err, docs) ->
console.log "Unable to save record: #{err}" if err
client.close()
?
client.open (err, database) ->
client.collection 'coffeescript_example', exampleSave
~~~
##### 查找記錄
~~~
mongo = require 'mongodb'
?
server = new mongo.Server "127.0.0.1", 27017, {}
?
client = new mongo.Db 'test', server, {w:1}
?
exampleFind = (dbErr, collection) ->
console.log "Unable to access database: #{dbErr}" if dbErr
collection.find({ _id: "my_favorite_latte" }).nextObject (err, result) ->
if err
console.log "Unable to find record: #{err}"
else
console.log result # => { id: "my_favorite_latte", flavor: "honeysuckle" }
client.close()
?
client.open (err, database) ->
client.collection 'coffeescript_example', exampleFind
~~~
##### 對于瀏覽器
一個[基于 REST 的接口](https://github.com/tdegrunt/mongodb-rest)在工程中,會提供基于 AJAX 的訪問通道。
### 討論
這個方法將 save 和 find 分開進單獨的實例,其目的是分散 MongoDB 指定的連接任務的關注點以及回收任務。[async 模塊](https://github.com/caolan/async)可以幫助這樣的異步調用。
### SQLite
### 問題
你需要 Node.js 內部與 [SQLite](http://www.sqlite.org/) 數據庫連接的接口。
### 解決方案
使用 [SQLite 模塊](http://code.google.com/p/node-sqlite/)。
~~~
sqlite = require 'sqlite'
?
db = new sqlite.Database
?
# The module uses asynchronous methods,
?
# so we chain the calls the db.execute
?
exampleCreate = ->
db.execute "CREATE TABLE snacks (name TEXT(25), flavor TEXT(25))",
(exeErr, rows) ->
throw exeErr if exeErr
exampleInsert()
?
exampleInsert = ->
db.execute "INSERT INTO snacks (name, flavor) VALUES ($name, $flavor)",
{ $name: "Potato Chips", $flavor: "BBQ" },
(exeErr, rows) ->
throw exeErr if exeErr
exampleSelect()
?
exampleSelect = ->
db.execute "SELECT name, flavor FROM snacks",
(exeErr, rows) ->
throw exeErr if exeErr
console.log rows[0] # => { name: 'Potato Chips', flavor: 'BBQ' }
?
# :memory: creates a DB in RAM
?
# You can supply a filepath (like './example.sqlite') to create/open one on disk
?
db.open ":memory:", (openErr) ->
throw openErr if openErr
exampleCreate()
~~~
### 討論
你也可以提前準備你的 SQL 查詢語句。
~~~
sqlite = require 'sqlite'
async = require 'async' # Not required but added to make the example more concise
?
db = new sqlite.Database
?
createSQL = "CREATE TABLE drinks (name TEXT(25), price NUM)"
?
insertSQL = "INSERT INTO drinks (name, price) VALUES (?, ?)"
?
selectSQL = "SELECT name, price FROM drinks WHERE price < ?"
?
create = (onFinish) ->
db.execute createSQL, (exeErr) ->
throw exeErr if exeErr
onFinish()
?
prepareInsert = (name, price, onFinish) ->
db.prepare insertSQL, (prepErr, statement) ->
statement.bindArray [name, price], (bindErr) ->
statement.fetchAll (fetchErr, rows) -> # Called so that it executes the insert
onFinish()
?
prepareSelect = (onFinish) ->
db.prepare selectSQL, (prepErr, statement) ->
statement.bindArray [1.00], (bindErr) ->
statement.fetchAll (fetchErr, rows) ->
console.log rows[0] # => { name: "Mia's Root Beer", price: 0.75 }
onFinish()
?
db.open ":memory:", (openErr) ->
async.series([
(onFinish) -> create onFinish,
(onFinish) -> prepareInsert "LunaSqueeze", 7.95, onFinish,
(onFinish) -> prepareInsert "Viking Sparkling Grog", 4.00, onFinish,
(onFinish) -> prepareInsert "Mia's Root Beer", 0.75, onFinish,
(onFinish) -> prepareSelect onFinish
])
~~~
[SQL 的 SQLite 版本](http://www.sqlite.org/lang.html)的以及 [node-SQLite](https://github.com/orlandov/node-sqlite#readme) 模塊文檔提供了更完整的信息。