将MongoDB服务器数据同步到IndexedDB本地存储

21

我正在尝试使用IndexedDB来解决离线问题,它将填充当前存储在MongoDB数据库(就是现在的)中的数据。

一旦数据存储在IndexedDB中,可能会在MongoDB服务器上更改,我需要传播这些更改。是否有任何现有的框架或库可以像这样为Mongo做某些事情?我已经知道CouchDB / PouchDB,并不探索这两个。


你应该看看 Meteor 的代码是否相关。 - Randall Hunt
非常有趣,谢谢。可能是我写离线应用程序的真正问题的解决方案。您应该将其作为答案,以便如果它确实解决了我的问题,我可以给您积分。 - Philippe Girolami
事实证明,完全离线的场景是不受支持的(离线登录+更改+在回到在线状态时与服务器同步):https://groups.google.com/d/topic/meteor-core/ZVj6RFbKDq0/discussion - Philippe Girolami
那么这个应用程序永远不会在线运行吗? - Randall Hunt
是的,它可以实现,但必须能够离线登录并执行操作。本质上是将数据库的一部分本地下载,并在连接时向服务器推送更改请求。 - Philippe Girolami
自从现在已经是2016年,你的问题变得更加相关,你是否找到了任何解决方案?或者目前只有CouchDB/PouchDB支持这个功能? - Matt Jensen
4个回答

6

[2021年同步解决方案]

我知道问题是针对MongoDB具体而言的,但由于这是一个旧帖子,我认为读者可能正在寻找新应用程序或重建的其他解决方案。我真的建议检查一下AceBase,因为它完全符合您当时要求的条件。

AceBase是一个免费且开源的实时数据库,可以轻松地在浏览器和服务器数据库之间进行存储和同步。它在浏览器中使用IndexedDB,在服务器上使用自己的二进制db / SQL Server / SQLite存储。离线编辑在重新连接时同步,并通过websocket(快速!)实时通知客户端进行远程数据库更改。

此外,AceBase还具有一种称为“实时数据代理”的独特功能,该功能允许将所有对内存对象的更改持久化并同步到本地和服务器数据库,并自动更新内存对象的远程更改。这意味着您可以完全忘记数据库编码,只需像使用本地对象一样进行编码,无论您在线还是离线。

以下示例展示了如何在浏览器中创建本地IndexedDB数据库,如何连接到与本地数据库同步的远程数据库服务器,以及如何创建实时数据代理以消除后续数据库编码。 AceBase还支持身份验证和授权,但出于简单起见,我将其省略了。

const { AceBaseClient } = require('acebase-client');
const { AceBase } = require('acebase');

// Create local database with IndexedDB storage:
const cacheDb = AceBase.WithIndexedDB('mydb-local');

// Connect to server database, use local db for offline storage:
const db = new AceBaseClient({ dbname: 'mydb', host: 'db.myproject.com', port: 443, https: true, cache: { db: cacheDb } });

// Wait for remote database to be connected, or ready to use when offline:
db.ready(async () => {

    // Create live data proxy for a chat:
    const emptyChat = { title: 'New chat', messages: {} };
    const proxy = await db.ref('chats/chatid1').proxy(emptyChat);  // Use emptyChat if chat node doesn't exist

    // Get object reference containing live data:
    const chat = proxy.value;

    // Update chat's properties to save to local database, 
    // sync to server AND all other clients monitoring this chat in realtime:
    chat.title = `Changing the title`;
    chat.messages.push({ 
        from: 'ewout', 
        sent: new Date(),
        text: `Sending a message that is stored in the database and synced automatically was never this easy!` +
              `This message might have been sent while we were offline. Who knows!`
    });

    // To monitor and handle realtime changes to the chat:
    chat.onChanged((val, prev, isRemoteChange, context) => {
        if (val.title !== prev.title) { 
            alert(`Chat title changed to ${val.title} by ${isRemoteChange ? 'us' : 'someone else'}`); 
        }
    });
});

了解更多示例和文档,请访问 npmjs.com 上的 AceBase 实时数据库引擎


2

使用简历令牌打开changeStream。但由于涉及多个不同的数据库,无法保证因果一致性。


1

我的方法是将所有数据与时间戳存储在本地存储中,并比较是否有任何时间戳与 MongoDB 的时间戳不同。在这种方法中,将修改的值从本地存储推送到 MongoDB,您不需要下载所有模式以及其他用户。我不知道它是否足够充分,如果有人有足够的信息和想法,请评论,我会进一步学习。

这是我的架构思路: enter image description here


0

我没有使用过IndexDB,但设计问题并不罕见。我理解你的应用程序是当客户端连接到MongoDB时,你会将一组文档下载到本地存储并断开连接。然后客户端可以在本地执行操作(未连接到数据服务器),然后推送更改。

我认为你需要处理两种一般情况:

  1. 当MongoDB服务器更新并中断与客户端的连续性时,客户端必须
    1. 轮询数据(定时器?)或
    2. 保持WebSocket打开以便让通知自由流动
  2. 当用户需要将更改的数据推回管道时
    1. 您可以异步重新连接,检查状态更改(根据您的业务规则解决冲突)
    2. 具有处理冲突的服务器端(轻量级)接口(根据您的应用程序的复杂性,比较MongoDB中状态更改的时间戳和IndexedDB更新应该足够)

你知道在这个领域中可能已经实现了什么吗?我们的使用方式更简单,因为本地永远不会进行任何更改。用户只能提出更改请求,然后将其推送到服务器并可能被接受和/或拒绝。如果被接受,它们必须被推回客户端。因此,在这种情况下,我们永远不可能在同一对象上具有本地和远程更改。 - Philippe Girolami
可能有一些关于backbone.js的东西,但那已经超出了我的能力范围。 - patrickgamer
1
MongoDB现在支持Change Streams,允许向客户端程序提供一系列变更的流。请参见https://docs.mongodb.com/manual/changeStreams。 - Joe Drumgoole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接