PouchDB is a NoSQL database, meaning that you store unstructured documents rather than explicitly specifying a schema with rows, tables, and all that jazz.
A document might look like this:
{
"_id": "mittens",
"name": "Mittens",
"occupation": "kitten",
"age": 3,
"hobbies": [
"playing with balls of yarn",
"chasing laser pointers",
"lookin' hella cute"
]
}
If you come from a SQL background, this handy conversion chart may help:
SQL concept | PouchDB concept |
---|---|
table | no equivalent |
row | document |
column | field |
primary key | primary key (_id ) |
index | view |
We'll discuss these concepts later on.
To store a document, you simply put
it:
const doc = {
"_id": "mittens",
"name": "Mittens",
"occupation": "kitten",
"age": 3,
"hobbies": [
"playing with balls of yarn",
"chasing laser pointers",
"lookin' hella cute"
]
};
db.put(doc);
Whenever you put()
a document, it must have an _id
field so that you can retrieve it later.
So now let's get()
the document by using its _id
:
db.get('mittens').then(function (doc) {
console.log(doc);
});
You should see:
{
"name": "Mittens",
"occupation": "kitten",
"age": 3,
"hobbies": [
"playing with balls of yarn",
"chasing laser pointers",
"lookin' hella cute"
],
"_id": "mittens",
"_rev": "1-bea5fa18e06522d12026f4aee6b15ee4"
}
You can see a live example of this code.
The document looks exactly the same as when we put it, except... aha! What is this? There is a new field, _rev
, that contains what looks like garbage. PouchDB gots some 'splainin' to do.
The new field, _rev
is the revision marker. It is a randomly-generated ID that changes whenever a document is created or updated.
Unlike most other databases, whenever you update a document in PouchDB or CouchDB, you must present the entire document along with its current revision marker.
For instance, to increment Mittens' age to 4, we would do:
doc.age = 4;
doc._rev = "1-bea5fa18e06522d12026f4aee6b15ee4";
db.put(doc);
If you fail to include the correct _rev
, you will get the following sad error:
{
"status": 409,
"name": "conflict",
"message": "Document update conflict"
}
HTTP 409
is a standard HTTP error message that indicates a conflict.
So to update Mittens' age, we will first need to fetch Mittens from the database, to ensure that we have the correct _rev
before we put them back. We don't need to manually assign the _rev
value here (like we did above), as it is already in the doc
we're fetching.
// fetch mittens
db.get('mittens').then(function (doc) {
// update their age
doc.age = 4;
// put them back
return db.put(doc);
}).then(function () {
// fetch mittens again
return db.get('mittens');
}).then(function (doc) {
console.log(doc);
});
You can see a live example of this code.
Now you should see the following:
{
"name": "Mittens",
"occupation": "kitten",
"age": 4,
"hobbies": [
"playing with balls of yarn",
"chasing laser pointers",
"lookin' hella cute"
],
"_id": "mittens",
"_rev": "2-3e3fd988b331193beeeea2d4221b57e7"
}
As you can see, we have successfully updated Mittens' age to 4 (they grow up so fast!), and their revision marker has also changed to "2-3e3fd988b331193beeeea2d4221b57e7"
. If we wanted to increment their age to 5, we would need to supply this new revision marker.
Now that you understand a bit about how to create and update documents, let's take a small detour to talk about asynchronous code.