MaxNoetzold / y-mongodb-provider

Mongodb database adapter for Yjs
MIT License
51 stars 10 forks source link

How to copy a new yDoc into mongodb? #5

Closed huanghantao closed 1 year ago

huanghantao commented 1 year ago

Here's my code:

  async duplicate(sourceFileId: string, destFileId: string): Promise<void> {
      const mdb = this.getMongodbPersistence();
      let sourceDocName = this.generateDocNameByFileId(sourceFileId);
      let destDocName = this.generateDocNameByFileId(destFileId);

      const sourceYdoc = await mdb.getYDoc(sourceDocName);
      const destYdoc = await mdb.getYDoc(destDocName);

      mdb.storeUpdate(destDocName, Y.encodeStateAsUpdate(sourceYdoc));
  }

However, the data stored in mongodb seems to be wrong. Can you guide me? I'm a novice, thank you!

MaxNoetzold commented 1 year ago

At first glance, your code appears to be fine. Could you please clarify what you mean when you say "the data stored in MongoDB seems to be incorrect"? Additionally, I can provide you with the code for how I would write the duplicate function. Perhaps it will be helpful:

const mdb = this.getMongodbPersistence();
const sourceDocName = this.generateDocNameByFileId(sourceFileId);
const destDocName = this.generateDocNameByFileId(destFileId);

const sourceYdoc = await mdb.getYDoc(sourceDocName);
const destYdoc = new Y.Doc();

const sourceStateVector = Y.encodeStateVector(sourceYdoc);
const diff = Y.encodeStateAsUpdate(destYdoc, sourceStateVector);

await mdb.storeUpdate(destDocName , diff);

tbh I am not an expert in the encoding of yjs updates either. Therefore, I cannot say for certain if my code is any different from yours. However, since both ydocs are not identical, I think that you need to "move" the update from one ydoc to the other. But again, I am not entirely sure.

I hope it helps.

huanghantao commented 1 year ago

@MaxNoetzold Thanks for your reply! I found a workable solution that seems to be working for now:

const mdb = this.getMongodbPersistence();
let sourceDocName = this.generateDocNameByFileId(sourceFileId);
let destDocName = this.generateDocNameByFileId(destFileId);

const sourceYdoc = await mdb.getYDoc(sourceDocName);
const destYdoc = await mdb.getYDoc(destDocName);

const sourceYArr = sourceYdoc.getArray<{ key: string; val: any }>(`${sourceFileId}`)
const sourceYStore = new YKeyValue(sourceYArr)

const records = sourceYStore.yarray.toJSON().map(({ val }) => ({ key: val.id, val: val }));

const destYArr = destYdoc.getArray<{ key: string; val: any }>(`${destFileId}`)
destYArr.insert(0, records)
mdb.storeUpdate(destDocName, Y.encodeStateAsUpdate(destYdoc));

But I'm not sure that's the best thing to do.