简体   繁体   English

使用PouchDB / CouchDB进行有效的数据库设计

[英]Efficient DB design with PouchDB/CouchDB

So I was reading a lot about how to actually store and fetch data in an efficient way. 因此,我读了很多关于如何有效地实际存储和获取数据的文章。 Basically my application is about time management/capturing for projects. 基本上,我的应用程序是关于项目的时间管理/捕获。 I am very happy for any opinion on which strategy I should use or even suggestions for other strategies. 对于我应该使用哪种策略的意见,甚至对其他策略的建议,我感到非常高兴。 The main concern is about the limited resources for local storage on the different Browsers. 主要问题在于在不同浏览器上用于本地存储的资源有限。

This is the main data I have to store: 这是我必须存储的主要数据:

db_projects: This is a database where the projects itself are stored. db_projects:这是一个用于存储项目本身的数据库。

db_timestamps: Here go the timestamps per project whenever a project is running. db_timestamps:在运行项目时,这里是每个项目的时间戳。


I came up with the following strategies: 我想出了以下策略:

1: Storing the status of the project in the timestamps 1:在时间戳中存储项目的状态

When a project is started, there is addad a timestamp to db_timestamps like so: 启动项目时,在db_timestamps中添加一个时间戳,如下所示:

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

This follows the strategy to only add data to the db and not modify any entries. 这遵循仅将数据添加到数据库而不修改任何条目的策略。 The problem I see here is that if I want to get all active projects for example, I would need to query the whole db_timestamp which can contain thousands of entries. 我在这里看到的问题是,例如,如果要获取所有活动项目,则需要查询整个db_timestamp,其中可以包含数千个条目。 Since I can not use the ID to search all active projects, this could result in a quite heavy DB query. 由于无法使用该ID搜索所有活动项目,因此可能会导致数据库查询非常繁重。

2: Storing the status of the project in db_projects 2:将项目状态存储在db_projects中

Each time a project changes it's status, there is a update to the project itself. 每次项目更改状态时,项目本身都会进行更新。 So the "get all active projects"-query would be much resource friendly, since there are a lot less projects than timestamps. 因此,“获取所有活动的项目”查询将非常节省资源,因为与时间戳相比,项目要少得多。 But this would also mean that each time a status change happens, the project entry would be revisioned and therefor would produce "a lot" of overhead. 但这也意味着每次状态更改时,项目条目都会被修改,因此会产生“大量”的开销。 I'm also not sure if the compaction feature would do a good job, since not all revision data is deleted (the documents are, but the leaf revisions not). 我也不确定压缩功能是否会做得很好,因为并非所有修订数据都被删除(文档被删除,但叶修订不被删除)。 This means for a state change we have at least the _rev information which is still a string of 34 chars for changing only the status (1 char). 这意味着对于状态更改,我们至少具有_rev信息,该信息仍然是34个字符的字符串,仅用于更改状态(1个字符)。 Or can I delete the leaf revisions after conflict resolution? 还是可以在解决冲突后删除叶子修订版?

3: Storing the status in a separate DB like db_status 3:将状态存储在单独的数据库中,例如db_status

This leads to the same problem as in #2 since status changes lead to revisions on this DB. 由于状态更改会导致对该数据库的修订,因此会导致与#2中的问题相同。 Or if the states would be added in "only add data"-mode (like in #1), it would just quickly fill with entries. 或者,如果状态将以“仅添加数据”模式添加(如#1),它将很快填充条目。

The general problem is that you have a limited amount of space that you could put into indexedDB. 普遍的问题是,您可以放入indexedDB的空间有限。 On the other hand the principle of ChouchDB is that storage space is cheap (which it is indeed true when you store on the server side only). 另一方面,ChouchDB的原理是存储空间便宜(仅当存储在服务器端时确实如此)。 Here an interesting discussion about that. 这里有一个有趣的讨论。

So this is the solution that I use for now. 这就是我现在使用的解决方案。 I am using a mix between solution 1 and solution 2 from above with the following additions: 我正在从上面的解决方案1和解决方案2之间混合使用,并添加了以下内容:

  1. Storing only the timesamps in a synced Database (db_timestamps) with the "only add data" principle. 遵循“仅添加数据”原则,仅将时间戳存储在同步数据库(db_timestamps)中。
  2. Storing the projects and their states in a separate local (not synced) database (db_projects). 将项目及其状态存储在单独的本地(未同步)数据库(db_projects)中。 Therefor I still use pouchDB since it has a lot simpler API than indexedDB. 因此,我仍然使用pouchDB,因为它的API比indexedDB简单得多。
  3. Storing the new/changed project status in each timestamp aswell (so you could rebuild db_projects out of db_timestams if needed) 还要在每个时间戳中存储新的/更改的项目状态(因此,可以根据需要在db_timestams中重建db_projects)
  4. Deleting db_projects every so often and repopulate it, so the revision data (overhead for this db in my case) is eliminated and the size is acceptable. 经常删除db_projects并重新填充它,这样就消除了修订数据(在我的情况下是该数据库的开销),并且大小是可以接受的。

I use the following code to rebuild my DB: 我使用以下代码重建数据库:

//--------------------------------------------------------------------
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
    };
}

So I not only use the pouchDB.destroy() command but also the indexedDB.deleteDatabase() command to get the storage freed nearly completely (there is still some 4kB that are not freed, but this is insignificant to me.) 因此,我不仅使用pouchDB.destroy()命令,还使用indexedDB.deleteDatabase()命令几乎完全释放了存储(仍然有一些4kB未被释放,但这对我来说无关紧要。)

The timings are not really proper but it works for me. 时间不是很恰当,但是对我有用。 I'm happy if somone has an idea to make the timing work properly (The problem for me is that indexedDB does not support promises). 如果somone有一个想法可以使计时正常工作,我感到很高兴(我的问题是indexedDB不支持promises)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM