preface

I’m currently working on a personal project based on Electron and Vue for a desktop application that needs to store and display index data for local audio files locally. I’m going to share this experience with you.

Offline storage tool selection

Offline storage can be implemented in many ways. The simplest are familiar browser-side offline storage such as LocalStorage and SessionStorage, or IndexedDB and Web SQL. The above four kinds of offline storage in the project can be achieved through the Chromium kernel in the Electron rendering process. Lightweight third-party libraries such as ImmortalDB and Web-storage-Cache offer some extensions to offline storage in browsers, but their maintenance is less than satisfactory. Still, forage has been remarkable.

Limited by the environment of browser kernel, the above methods cannot well meet my requirements, so I can only look for storage tools on node.js side, which can be divided into two categories: one is the implementation of JS itself (such as NeDB and PouchDB), and the other is mature database software (such as MySQL and MongoDB).

According to the function and performance, the database is the optimal choice, but not very accord with my Electron application of positioning, 1, their volume is very large, need to be packed into the user’s installation package (hard to implement, didn’t also a few for ordinary users to be able to bear a small software on your computer to MySQL); The function is huge, how to kill a chicken with a knife?

So NeDB and PouchDB, which take up no space, are lightweight and easy to pack. Considering that NeDB is plaintext storage, it has a single function and is in disrepair. I chose PouchDB next door.

Introduction to PouchDB

Let’s take a look at the PouchDB website to introduce the product:

PouchDB is an open-source JavaScript database inspired by Apache CouchDB that is designed to run well within the browser.



PouchDB was created to help web developers build applications that work as well offline as they do online.

PouchDB runs in both the browser and Node.js environment. It is lightweight, portable and easy to use. PouchDB uses IndexedDB by default in the browser. If the current environment does not support it, go back to Web SQL. In a Node.js environment, data is stored in a local file in a specific format. This section of the official documentation details how 👉Adapters work in different environments.

The installation

The official document provides two methods, namely CDN and NPM:

<script src="/ / cdn.jsdelivr.net/npm/[email protected]/dist/pouchdb.min.js"></script>
Copy the code
npm install --save pouchdb
Copy the code

Initialize the

Pouchdb creates a database instance using the pouchdb constructor in the node environment:

const PouchDB = require('pouchdb')
// Create a database named my_database under the database folder in the root directory
const db = new PouchDB('database/my_database')
Copy the code

The new PouchDB([name], [options]) method takes a database name and configuration items as parameters (see the documentation for configuration items). In addition to accepting the name, the name parameter can also be passed in the remote CouchDB database address, such as const db = new PouchDB(‘http://pouch-db.com/my-db’).

However, the official documentation does not say enough about where the database is stored in node. In node, name can be a relative path or an absolute path, as follows:

// Create it in {root}/database/my_database
const db = new PouchDB('database/my_database')
// Create in C:/Code/test/test_pouchdb
const db2 = new PouchDB('D:/Code/test/test_pouchdb')
Copy the code

Basic operation

At its most basic, a database is simply a quick and easy WAY to do CRUD. Let’s quickly implement the basic operations of PouchDB. All related operations can be found in their API documentation.

increase

First, we need to define the format of the data to be stored:

const myData = {
  _id: String.title: String
}
Copy the code

Second, it is best to use uniform functions to add data, because there is no strict schema in PouchDB. We use db.put(doc, [options], [callback]) to add or modify data.

It should be pointed out that,PouchDBExcept for the traditional onescallbackAnd support more mainstream onesPromise 与 async 。

// * Use functions to wrap new data
function addData(title) {
  // Data format
  const data = {
    _id: new Date().toISOString(),
    title: text
  }
  // Add method
  db.put(data, function cb(err, result) {
    if (err) {
      console.error(err)
    } else {
      console.log(result)
    }
  })
}
Copy the code

We use the addData() method to create data with title ‘helloPouchDB’ and see what it contains:

addData('helloPouchDB')
Copy the code

Result in the callback returns the newly added state, the ID of the data, and rev. In addition to title, the data also has the corresponding _id and _rev.

// result
{
  ok: true.id: 'the 2020-12-04 T12: all the well-being 638 z'.rev: '1-a2436e9326998a520a759f2a274e166b'
}
// Save the data
{
  title: 'helloPouchDB'._id: 'the 2020-12-04 T12: all the well-being 638 z'._rev: '2-565fec0bf70044cc51d24a8379139f8e'
}

Copy the code

Note that modifying data requires specifying the _rev of the current modified data item (which was created by default). Like this:

db.put({
  title: 'Nice to meet you'._id: 'the 2020-12-04 T12: all the well-being 638 z'._rev: '2-565fec0bf70044cc51d24a8379139f8e'
})
Copy the code

check

Db.get (docId, [options], [callback]) is used to fetch data from the database by id, such as db.get(_id). One or more rev can be specified in the configuration item. Refer to the documentation for other configuration items.

Use db.alldocs ([options], [callback]) (document portal) if you need to fetch multiple data. Skip and limit can be specified in configuration items to enable paging.

function showData() {
  db.allDocs({
    include_docs: true.// By default, only id and rev are returned
    descending: true.// in descending order
    skip: 20./ / page 3
    limit: 10 // 10 entries per page
  })
    .then((res) = > {
      console.log(res)
    })
    .catch((err) = > {
      console.error(err)
    })
}
Copy the code

The returned data contains the total number of rows, the number of skipped rows, and the array rows of data. The format is as follows:

{
  total_rows: 1.offset: 0.rows: [{id: 'the 2020-12-04 T13:00:26. 358 z'.key: 'the 2020-12-04 T13:00:26. 358 z'.value: { rev: '1-6da27cff722c24cfe38fb09be78f8576' },
      doc: {
        title: 'helloPouchDB'._id: 'the 2020-12-04 T13:00:26. 358 z'._rev: '1-6da27cff722c24cfe38fb09be78f8576'}}}]Copy the code

The next most important query method is db.find(request [, callback]). This method allows the data document portal to be queried by the fields of the data. Note that this method requires the introduction of the pouchdb-find plug-in.

# installation
npm install --save pouchdb-find
Copy the code
const PouchDB = require('pouchdb')
// Inject the plug-in
PouchDB.plugin(require('pouchdb-find'))
Copy the code

Db.find () specifies the query content with selector, and fields specifies the fields to be returned. Selector can also specify special query conditions using $lt, $gt, and other filters. As with db.alldocs (), skip and limit can be specified.

db.find({
  selector: {
    title: 'helloPouchDB',},fields: ['_id'.'name'],})Copy the code

Change, delete

By combining the new and query methods, we can retrieve the existing data and modify it with db.put() :

/ / query
db.find({
  selector: {
    title: 'helloPouchDB',
  },
})
  .then((res) = > {
  // Get the data
    const result = res.docs[0]
    // Modify the data
    result.title = 'Nice to meet you'
    // Modify and write
    db.put(result)
      .then((res) = > {
        console.log('yes! ')
      })
      .catch((err) = > {
        console.error(err)
      })
  })
  .catch((err) = > {
    console.error(err)
  })
Copy the code

Remove (doc, [options], [callback]), which accepts doc objects as well as delete data by id and rev.

// Approach 1 - Get the instance and delete it
db.get(_id, function(err, doc) {
  if (err) { return console.log(err) }
  db.remove(doc, function(err, response) {
    if (err) { return console.log(err) }
  })
})
// Mode 2 - Delete by id and rev
db.remove(doc._id, doc._rev, function(err, response) {
    if (err) { return console.log(err) }
  })
})
Copy the code