PouchDB/CouchDB 的高效数据库设计

Efficient DB design with PouchDB/CouchDB

所以我阅读了很多有关如何以高效方式实际存储和获取数据的资料。基本上我的申请是关于项目的时间 management/capturing。对于我应该使用哪种策略的任何意见,甚至对其他策略的建议,我都非常高兴。主要担心的是不同浏览器上本地存储的资源有限。

这是我要存储的主要数据:

db_projects: This is a database where the projects itself are stored.

db_timestamps: Here go the timestamps per project whenever a project is running.


我想出了以下策略:

1:在时间戳中存储项目的状态

当项目启动时,db_timestamps 会添加一个时间戳,如下所示:

db_timestamps.put({
   _id: String(Date.now()),
   title: projectID,
   status: status //could be: 1=active/2=inactive/3=paused
})...

这遵循 only add data 数据库的策略,不修改任何条目。我在这里看到的问题是,例如,如果我想获取所有活动项目,我需要查询整个 db_timestamp,它可以包含数千个条目。由于我不能使用 ID 来搜索所有活动项目,这可能会导致非常繁重的数据库查询。

2:在db_projects

中存储项目的状态

每次项目更改其状态时,项目本身都会更新。因此,“获取所有活动项目”查询将更加资源友好,因为项目比时间戳少得多。但这也意味着每次发生状态更改时,项目条目都会被修改,因此会产生“大量”开销。我也不确定 compaction feature 是否会做得很好,因为并非所有修订数据都被删除(文档是,但叶修订不是)。这意味着对于状态更改,我们至少有 _rev 信息,它仍然是一个 34 个字符的字符串,用于仅更改状态(1 个字符)。或者我可以在冲突解决后删除叶修订吗?

3:将状态存储在单独的数据库中,如 db_status

这会导致与 #2 中相同的问题,因为状态更改会导致对该数据库进行修改。或者,如果以“仅添加数据”模式添加状态(如#1),它会很快填充条目。

一般问题是您可以放入 indexedDB 的 space 数量有限。另一方面,ChouchDB 的原则是存储 space 很便宜(仅在服务器端存储时确实如此)。 Here an interesting discussion about that.

所以这是我现在使用的解决方案。我混合使用了上面的解决方案 1 和解决方案 2,并添加了以下内容:

  1. 根据 "only add data" 原则在同步数据库 (db_timestamps) 中仅存储时间戳。
  2. 将项目及其状态存储在单独的本地(不是 同步)数据库(db_projects)。因此,我仍然使用 pouchDB,因为 它比 indexedDB 更简单API。
  3. 存储 new/changed 每个时间戳中的项目状态(这样你就可以重建 db_projects 如果需要,从 db_timestams 中取出)
  4. 经常删除 db_projects 并重新填充它,所以 修订数据(在我的例子中是这个数据库的开销)被消除并且大小是可以接受的。

我使用以下代码重建我的数据库:

//--------------------------------------------------------------------
function rebuild_db_project(){   
    db_project.allDocs({
      include_docs: true,
      //attachments: true
    }).then(function (result) {
        // do stuff
        console.log('I have read the DB and delete it now...');
        deleteDB('db_project', '_pouch_DB_Projekte');
        return result;
    }).then(function (result) {
        console.log('Creating the new DB...'+result);
        db_project = new PouchDB('DB_Projekte');

        var dbContentArray = [];
        for (var row in result.rows) {
            delete result.rows[row].doc._rev; //delete the revision of the doc. else it would raise an error on the bulkDocs() operation
            dbContentArray.push(result.rows[row].doc);
        }
        return db_project.bulkDocs(dbContentArray);      
    }).then(function(response){
        console.log('I have successfully populated the DB with: '+JSON.stringify(response));
    }).catch(function (err) {
      console.log(err);
    });  
}

//--------------------------------------------------------------------
function deleteDB(PouchDB_Name, IndexedDB_Name){
    console.log('DELETE');

    new PouchDB(PouchDB_Name).destroy().then(function () {
      // database destroyed
      console.log("pouchDB destroyed.");
    }).catch(function (err) {
      // error occurred
    });

    var DBDeleteRequest = window.indexedDB.deleteDatabase(IndexedDB_Name);
    DBDeleteRequest.onerror = function(event) {
      console.log("Error deleting database.");
    };
    DBDeleteRequest.onsuccess = function(event) {
      console.log("IndexedDB deleted successfully"); 
      console.log(request.result); // should be null
    };
}

所以我不仅使用 pouchDB.destroy() 命令而且还使用 indexedDB.deleteDatabase() 命令来几乎完全释放存储(还有一些 4kB 没有被释放,但是这个对我来说微不足道。)

时间安排不太合适,但对我有用。如果有人有想法让计时正常工作,我很高兴(对我来说问题是 indexedDB 不支持承诺)。