PouchDB是一款数据库。它可以在浏览器里面存储你的本地信息,所以适合于基于浏览器的可离线存储方案。PouchDB实际上是一个JavaScript库。
快速入门
可以参考Getting Started Guide入门PouchDB。
安装PouchDB与使用
安装:`npm install pouchdb --save`
使用:`var PouchDB = require('pouchdb');`
简单操作
新增与修改数据
db.put({},function callback(err,result){})
。新的数据中每一条都要有一个唯一的主键_id
,在提交的数据里,如果存在与数据库中相同的_id
,PouchDB就将更新该数据,否者就创建一条新数据。使用db.post
可以提交没有_id
的数据。回调函数callback中:如果err为非空,说明插入数据失败;如果err为空,则表示插入成功,result里返回成功后数据_id
和_rev
,_rev
代表这条数据的版本号。
删除数据
db.remove()
。删除数据的时候,我们需要同时提供_id
和_rev
项。我们使用remove()
的时候,并没有真正删除掉文档,它只是被添加了一个_deleted
标志,值为true。以下3种写法都可以删除数据:
db.get('mittens').then(function (doc) {
return db.remove(doc);
});
db.get('mydoc').then(function (doc) {
return db.remove(doc._id, doc._rev);
});
db.get('mydoc').then(function (doc) {
doc._deleted = true;
return db.put(doc);
});
查询数据
db.get(_id)
获得指定的数据
在浏览器中查看PouchDB
通过PouchDB Inspector,它是用于在Chrome中查看PouchDB的插件。
通过浏览器中的IndexedDB/WebSQL查看。
debug模式
开启debug模式:PouchDB.debug.enable('*')
关闭debug模式:PouchDB.debug.disable()
删除本地数据库
在Chrome中,通过使用ClearBrowserData extension插件删除
在Firefox中,通过使用Clear Recent History+ add-on插件删除
在Safari中,通过 Safari → Clear History and Website Data 删除
通过代码:db.destroy()
,返回的是一个Promise
理解revisions(_rev)
字段_rev
是一个版本标志。它是在新增或者修改的时候生成的一个随机数。在PouchDB中,更新数据的时候必须要有_rev
字段作为条件。如:
var doc = {
'_id': 'mittens',
'_rev': '1-7df5244f3d6cf5d5b260b9c641f9c604',
'name': 'Mittens',
'occupation': 'kitten',
'age': 4,
'hobbies': [
'playing with balls of yarn',
'chasing laser pointers',
"lookin' hella cute"
]
}
如果没有_rev
字段,更新的时候就会报错。
{
status: 409,
name: 'conflict',
message: 'Documentupdateconflict',
error: true
}
为什么我们一定需要_rev
呢?因为使用_rev
可以更好地进行同步工作
Asynchronous Code
PouchDB提供了一个完全异步API。
callback形式:
db.get('mittens', function (error, doc) {
if (error) {
// oh noes! we got an error
} else {
// okay, doc contains our document
}
});
Promise形式:
db.get('mittens').then(function (doc) {
// okay, doc contains our document
}).catch(function (err) {
// oh noes! we got an error
});
批量操作
可以使用bulkDocs()和allDocs()进行批量操作
使用bulkDocs()一次性操作多个doc
db.bulkDocs([
{
_id: 'mittens',
occupation: 'kitten',
cuteness: 9.0
},
{
_id: 'katie',
occupation: 'kitten',
cuteness: 7.0
},
{
_id: 'felix',
occupation: 'kitten',
cuteness: 8.0
}
])
使用bulkDocs()
可以在一次请求中进行处理操作。我们也可以使用bulkDocs()
批量修改或者批量删除,每个对象中都包含_rev
和_deleted
即可。
因为PouchDB并不支持事务。所以在bulkDocs()中,一个操作失败了,并不能确保所有的操作都失败。
使用allDocs()一次性读取多个doc
我们使用allDocs()返回的数据是按照_id
排序的。
db.allDocs({include_docs: true}).then(res => {
console.log(JSON.stringify(res))
})
如果我们没有传入include_docs: true
只会返回基本的id、key和value.rev。
在allDocs()中,你可以进行排序、过滤等操作。可以通过阅读“Pagination strategies with PouchDB”获悉如何进行分页操作。
附件操作
PouchDB支持附件操作
如何存储附件
可以使用base64-encoded格式或者Blob进行存储附件。
存储一个附件:
db.put({
_id: 'mydoc',
_attachments: {
'myattachment.txt': {
content_type: 'text/plain',
data: 'aGVsbG8gd29ybGQ='
}
}
})
以上代码中,myattachment.txt
是文件名;content_type
是格式;aGVsbG8gd29ybGQ=
是base64编码后的数据。
我们如何读取附件呢?
db.get('mydoc').then(data => {
console.log(data)
})
使用以上代码时,PouchDB只会附件的基本信息,返回:
{
_attachments: {
myattachment.txt: {
content_type: "text/plain",
digest: "md5-XrY7u+Ae7tCTyyK7j1rNww==",
length: 11,
revpos: 1,
stub: true
}
},
_id: "mydoc",
_rev: "1-a2308e4759440419de42048838ed86d3"
}
要获得附件内容,我们必须得在查询中添加参数:attachments: true
。
db.get('mydoc', {attachments: true}).then(data => {
console.log(data)
})
图片附件
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)
})
上面代码中,我们使用URL.createObjectURL(),将Blob转换成URL。
上面代码更值得让我们注意的是,使用了db.getAttachment
方法。该方法返回一个Blob,而不是返回base64编码的String。不过我们可以在base64和blob直接互转。
直接存储二进制数据
可以直接使用putAttachment()
方法,如果已经存在附件则该方法将覆盖已存在的附件,如果不存在附件则创建一个新的附件。
在NodeJS中,PouchDB返回的Blobs被Buffers代替。同样的,在PouchDB中,NodeJS的Buffers被Blobs替代。
附件上传
可以使用H5的File
API上传附件,也可以使用<input type="file">
进行附件上传,而且它们的元素已经是Blob。以下是一个简单的例子:
<input type="file">
var input = document.querySelector('input');
input.addEventListener('change', function () {
var file = input.files[0]; // file is a Blob
db.put({
_id: 'mydoc',
_attachments: {
filename: {
type: file.type,
data: file
}
}
}).catch(function (err) {
console.log(err);
});
});
Base64 vs Blobs/Buffers
PouchDB将根据Base64格式的数据或者Blobs/Buffers数据选择最佳的存储结构。
根据官方例子的代码,我们可以在使用put()保存Blobs,也可以使用putAttachment()保存Base64。getAttachment()方法总是返回Blobs。在各个查询方法中,都可以传入选项{attachments: true}
,返回Base64;传入参数{binary: true}
返回二进制。