GUIDES
1.建立couchDB環境
-
下載並安裝CouchDB:
https://couchdb.apache.org/#download -
測試:
- 於CMD下,執行
curl localhost:5984
- 打開
http://localhost:5984/_utils/fauxton/
或http://localhost:5984/_utils/
以進入 CouchDB界面
- 於CMD下,執行
-
Set _utilsp CORS (用於跨域)
- 安裝:於CMD下,執行
npm install -g add-cors-to-couchdb
- 運行:於CMD下,執行
add-cors-to-couchdb
- 安裝:於CMD下,執行
2.建立PouchDB環境
- 下載
- 在html頁面引入
<script src="pouchdb-3.4.0.min.js"></script>
3.使用pouchdb數據庫
本地數據庫
//創建數據庫:
var db = new PouchDB('kittens');
遠程數據庫
//創建數據庫:
var db = new PouchDB('http://localhost:5984/kittens');
打開http://localhost:5984/kittens
可以預覽數據庫信息
地址解析:
http:// localhost:5984 /kittens
|_____| |____________| |_____|
| | |
Protocol Where CouchDB database
(https if itself is name
Cloudant) hosted
使用info獲取數據庫信息
db.info().then(function (info) {
console.log(info);
})
刪除本地的所有數據庫(Chrome)
- 使用ClearBrowserData
- 清除瀏覽器緩存
4.使用文檔數據
文檔數據結構:
SQL concept PouchDB concept
table <=> no equivalent(不存在表格)
row <=> document(相當於doc)
column <=> field(值域)
primary <=> key primary key (_id)
index <=> view
定義一個doc結構對象,*doc對象必須要有_id屬性
var doc = {
"_id": "mittens",
"name": "Mittens",
"occupation": "kitten",
"age": 3,
"hobbies": [
"playing with balls of yarn",
"chasing laser pointers",
"lookin' hella cute"
]
};
使用put方法存儲到數據庫
db.put(doc);
獲取數據:(根據_id獲取)
db.get('mittens').then(function (doc) {
console.log(doc);
});
數據版本 (_rev)
_rev:
- 版本標志位
- 操作數據時,需要設置該屬性
更新數據方法:
手動設置該屬性
doc.age = 4;
doc._rev = "1-bea5fa18e06522d12026f4aee6b15ee4";//(傳入當前的_rev屬性)
db.put(doc);
獲取當前數據,此時即包含_rev屬性
db.get('mittens').then(function (doc) {
// update his age
doc.age = 4;
// put him back
return db.put(doc);
}).then(function () {
// fetch mittens again
return db.get('mittens');
}).then(function (doc) {
console.log(doc);
});
更新數據時,需要傳入當前的_rev屬性,若不輸入_rev屬性,會報錯如下:
{
"status": 409,
"name": "conflict",
"message": "Document update conflict"
}
5.異步處理數據
callback:
db.get('mittens', function (error, doc) {
if (error) {
// oh noes! we got an error
} else {
// okay, doc contains our document
}
});
promises:
db.get('charlie').then(function (charlie) {
// Within this function, you can do
// try/catch/return like you normally would,
// and it will be handled asynchronously!
}).then(function (result) {
// If the previous function returned something
// (or returned undefined), it will show up here
// as "result".
}).catch(function (err) {
// If the previous function threw an error,
// it will show up here as "err".
});
6.更新刪除數據
創建一個默認的doc(若存在則獲取,不存在則創建)
db.get('config').catch(function (err) {
if (err.status === 404) { // not found!
return {
_id: 'config',
background: 'blue',
foreground: 'white',
sparkly: 'false'
};
} else { // hm, some other error
throw err;
}
}).then(function (configDoc) {
// sweet, here is our configDoc
}).catch(function (err) {
// handle any errors
});
刪除數據
When you remove() a document, it's not really deleted; it just gets a _deleted attribute added to it)
//1)直接remove doc
db.get('mydoc').then(function (doc) {
return db.remove(doc);
});
//2) 使用_id,_rev
db.get('mydoc').then(function (doc) {
return db.remove(doc._id, doc._rev);
});
//3) 將_deleted字段設為true
db.get('mydoc').then(function (doc) {
doc._deleted = true;
return db.put(doc);
});
7.Bulk operations (批量操作)
bulkDocs():(批量插入)
db.bulkDocs([
{
_id: 'mittens',
occupation: 'kitten',
cuteness: 9.0
},
{
_id: 'katie',
occupation: 'kitten',
cuteness: 7.0
},
{
_id: 'felix',
occupation: 'kitten',
cuteness: 8.0
}
]);
allDocs() 批量查詢
db.put({
_id: new Date().toJSON(),
name: 'Mittens',
occupation: 'kitten',
cuteness: 9.0
}).then(function () {
return db.put({
_id: new Date().toJSON(),
name: 'Katie',
occupation: 'kitten',
cuteness: 7.0
});
}).then(function () {
return db.put({
_id: new Date().toJSON(),
name: 'Felix',
occupation: 'kitten',
cuteness: 8.0
});
]).then(function () {
return db.allDocs({include_docs: true});
}).then(function (response) {
console.log(response);
}).catch(function (err) {
console.log(err);
});
8.使用 attachments
base64:
btoa('hello world') <=> "aGVsbG8gd29ybGQ="
atob('aGVsbG8gd29ybGQ=') <=> "hello world"
Image attachments
db.put({
_id: 'meowth',
_attachments: {
'meowth.png': {
content_type: 'image/png',
data: 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAIAAAB0Xu9BAAAABGdBTUEAALGPC/xhBQAAAuNJREFUWEetmD1WHDEQhDdxRMYlnBFyBIccgdQhKVcgJeQMpE5JSTd2uqnvIGpVUqmm9TPrffD0eLMzUn+qVnXPwiFd/PP6eLh47v7EaazbmxsOxjhTT88z9hV7GoNF1cUCvN7TTPv/gf/+uQPm862MWTL6fff4HfDx4S79/oVAlAUwqOmYR0rnazuFnhfOy/ErMKkcBFOr1vOjUi2MFn4nuMil6OPh5eGANLhW3y6u3aH7ijEDCxgCvzFmimvc95TekZLyMSeJC68Bkw0kqUy1K87FlpGZqsGFCyqEtQNDdFUtFctTiuhnPKNysid/WFEFLE2O102XJdEE+8IgeuGsjeJyGHm/xHvQ3JtKVsGGp85g9rK6xMHtvHO9+WACYjk5vkVM6XQ6OZubCJvTfPicYPeHO2AKFl5NuF5UK1VDUbeLxh2BcRGKTQE3irHm3+vPj6cfCod50Eqv5QxtwBQUGhZhbrGVuRia1B4MNp6edwBxld2sl1splfHCwfsvCZfrCQyWmX10djjOlWJSSy3VQlS6LmfrgNvaieRWx1LZ6s9co+P0DLsy3OdLU3lWRclQsVcHJBcUQ0k9/WVVrmpRzYQzpgAdQcAXxZzUnFX3proannrYH+Vq6KkLi+UkarH09mC8YPr2RMWOlEqFkQClsykGEv7CqCUbXcG8+SaGvJ4a8d4y6epND+pEhxoN0vWUu5ntXlFb5/JT7JfJJqoTdy9u9qc7ax3xJRHqJLADWEl23cFWl4K9fvoaCJ2BHpmJ3s3z+O0U/DmzdMjB9alWZtg4e3yxzPa7lUR7nkvxLHO9+tvJX3mtSDpwX8GajB283I8R8a7D2MhUZr1iNWdny256yYLd52DwRYBtRMvE7rsmtxIUE+zLKQCDO4jlxB6CZ8M17GhuY+XTE8vNhQiIiSE82ZsGwk1pht4ZSpT0YVpon6EvevOXXH8JxVR78QzNuamupW/7UB7wO/+7sG5V4ekXb4cL5Lyv+4IAAAAASUVORK5CYII='
}
}
}).then(function () {
return db.getAttachment('meowth', 'meowth.png');
}).then(function (blob) {
var url = URL.createObjectURL(blob);
var img = document.createElement('img');
img.src = url;
document.body.appendChild(img);
}).catch(function (err) {
console.log(err);
});
9.Replication(同步/拷貝 數據)
1.創建本地數據庫
var localDB = new PouchDB('mylocaldb')
2.創建要要遠程的數據庫
var remoteDB = new PouchDB('http://localhost:5984/myremotedb')
3.同步本地數據庫到遠程的數據庫
localDB.replicate.to(remoteDB).on('complete', function () {
// yay, we're done!
}).on('error', function (err) {
// boo, something went wrong!
});
4.雙向復制
localDB.replicate.to(remoteDB);
localDB.replicate.from(remoteDB);
or
localDB.sync(remoteDB);
localDB.sync(remoteDB).on('complete', function () {
// yay, we're in sync!
}).on('error', function (err) {
// boo, we hit an error!
});
5.同步的應答操作
//1.To enable live replication, you simply specify {live: true}:
localDB.sync(remoteDB, {
live: true
}).on('change', function (change) {
// yo, something changed!
}).on('error', function (err) {
// yo, we got an error! (maybe the user went offline?)
})));
//2.You can allow PouchDB to automatically handle this error, and retry until the connection is re-established, by using the retry option:
localDB.sync(remoteDB, {
live: true,
retry: true
}).on('change', function (change) {
// yo, something changed!
}).on('paused', function (info) {
// replication was paused, usually because of a lost connection
}).on('active', function (info) {
// replication was resumed
}).on('error', function (err) {
// totally unhandled error (shouldn't happen)
})));
6.取消同步
//1.
var syncHandler = localDB.sync(remoteDB, {
live: true,
retry: true
});
syncHandler.on('complete', function (info) {
// replication was canceled!
});
syncHandler.cancel(); // <-- this cancels it
//2.
var replicationHandler = localDB.replicate.to(remoteDB, {
live: true,
retry: true
});
replicationHandler.on('complete', function (info) {
// replication was canceled!
});
replicationHandler.cancel(); // <-- this cancels it
10.Map/reduce queries
臨時創建:
//emit()的內容 是 用於查詢時的數據(key對應的字段)
//此處的意思就是創建一個index,查找doc.name 為 'foo'的所有數據
db.query(function (doc, emit) {
emit(doc.name);
}, {key: 'foo'}).then(function (result) {
// found docs with name === 'foo'
}).catch(function (err) {
// handle any errors
});
持久性創建:
首先創建一個視圖(index)
//注意 _id 命名規范以 _design/ 開頭
var ddoc = {
_id: '_design/my_index',
views: {
//以name為查找的屬性
by_name: {
map: function (doc) {
emit(doc.name);
}.toString()
}
}
};
// save it
pouch.put(ddoc).then(function () {
// success!
}).catch(function (err) {
// some error (maybe a 409, because it already exists?)
});
然后就可以通過id,視圖名直接使用
//查找name 為test的數據
db.query('my_index/by_name',{
key:'test'
}).then(function (res) {
// got the query results
}).catch(function (err) {
// some error
});
//第一次使用的時候因為要創建視圖會相對慢,可以先實行一個空的查詢讓其先建立視圖
db.query('my_index/by_name', {
limit: 0 // don't return any results
}).then(function (res) {
// index was built!
}).catch(function (err) {
// some error
});
Map functions
//Map functions:
function myMapFunction(doc) {
if (doc.type === 'pokemon') {
if (doc.name === 'Pikachu') {
emit('Pika pi!');
} else {
emit(doc.name);
}
}
}
// find pokemon with name === 'Pika pi!'
pouch.query(myMapFunction, {
key : 'Pika pi!',
include_docs : true
}).then(function (result) {
// handle result
}).catch(function (err) {
// handle errors
});
// find the first 5 pokemon whose name starts with 'P'
pouch.query(myMapFunction, {
startkey : 'P',
endkey : 'P\uffff',
limit : 5,
include_docs : true
}).then(function (result) {
// handle result
}).catch(function (err) {
// handle errors
});
//Reduce functions:
// emit the first letter of each pokemon's name
var myMapReduceFun = {
map: function (doc) {
emit(doc.name.charAt(0));
},
reduce: '_count'
};
// count the pokemon whose names start with 'P'
pouch.query(myMapReduceFun, {
key: 'P', reduce: true, group: true
}).then(function (result) {
// handle result
}).catch(function (err) {
// handle errors
});
11.壓縮,刪除數據庫
Compacting a database
return db.compact().then(function (info) {
// compaction complete
}).catch(function (err) {
// handle errors
});
Auto-compaction
var db = new PouchDB('mydb', {auto_compaction: true});
Destroying a database
PouchDB.destroy('mydb').then(function () {
// database destroyed
}).catch(function (err) {
// error occurred
})