Deleting documents in ShareDB

208 views
Skip to first unread message

Stanley Sakai

unread,
Jul 8, 2016, 3:01:59 AM7/8/16
to ShareJS
Hi guys!

I've been using ShareJS for a while and am glad to see the continual progress being made. 😃

But this question has me stumped. I've probably spent at least four hours trying to solve it this afternoon to no avail.

I'm switching over from a previous setup in a project I'm working on where I used ShareJS 0.7 and livedb-mongo, transitioning to just ShareDB. Before, I would delete documents off the database via:

var db      = require('livedb-mongo')(configdb.url, { safe : true });
var backend = livedb.client(db);

 backend.submit(author, title, {del: true}, function(err) {
        if (err) {
          console.log("There was an error: " + err);
        } else {
          console.log("Yay! BAI: " + author + ", " + title);
        }
 
Say I executed the above. When I would try to reconnect my textarea using whatever I'd passed in as "author" and "title," it would point to a blank (now deleted) document. Hurray!

After reading through the readme, I gathered that the way to do this in ShareDB is via this but maybe I'm completely wrong:

var db         = require('sharedb-mongo')(dbConfig.aloft);
var backend    = ShareDB({db: db});
var connection = backend.connect();
var doc        = connection.get(author, title);

if (doc) { // If there actually is a match with author & title, then proceed.
       doc.del(function (err) {
          if (err) {
            console.log('there was an error: ' + err);
          } else {
            console.log('deleted successfully.');
          }
        })
      }

I keep getting "there was an error: Error: Document does not exist" and when I reconnect to the doc with whatever I assigned to "author" and "title," everything is obviously still there.

So I must not be invoking connection.get() correctly to find the matching document before actually executing the del command? Also, in the readme it says correct syntax for del is doc.del([options][, function(err) {...}]) takes options as the first parameter, but I don't know what "options" should be in this case. There isn't any explanation as to what "options" there are or how to correctly define/format them for .del().

Is .del() used to delete operations or is it used to delete entire document objects?

All I'm trying to do is delete the contents of a document so that when you reconnect to it, it's blank rather than what was last written to it.

I hope this makes sense. Apologies if this is a really basic question. I can't seem to get what the readme is telling me no matter how many times I read it. ☹️

Thanks!

-S

Nate Smith

unread,
Jul 8, 2016, 3:16:22 PM7/8/16
to sha...@googlegroups.com
Hey Stanley!

This behavior should actually be pretty much the same between ShareJS 0.7 and ShareDB, but these two examples are doing different things.


1. In the first example, you are submitting an operation to the backend without creating a client. In most cases, you don't want to do this, but you can see the interface in the code here: https://github.com/share/sharedb/blob/033bfa1bef2ba54606cbda6738f460a1f8cdd7f4/lib/backend.js#L152. For completeness, what that would look like in ShareDB is:

var db = require('sharedb-mongo')(dbConfig.aloft);
var backend = ShareDB({db: db});

backend.submit(null, author, title, {del: true}, function(err) {
  if (err) throw err;
});

The only difference from ShareJS 0.7 is the addition of the agent argument, which is passed through in middleware in case you want to add some state used for doing access control of a specific client, cache data for a specific client, or otherwise identify a client on the server.

The reason this worked before (and should still work, though I didn't explicitly test it) is that if you submit an op with a null version, it is simply applied as the most recent version, effectively last writer wins instead of doing OT. This is generally fine in the delete or create case, but generally you don't want to blindly submit operations without versions. The client's job is to create operations with known base versions and OT them against other operations on the same document in a collaborative setting. But to do anything with a client document, you have to fetch the current data so that it knows what the base version is.


2. The reason the example you've provided here does not work as expected is that you did not fetch or subscribe the current document state, so the del method raises an exception. You can only use doc.submitOp or doc.del methods after a fetch or subscribe of the doc.

var db = require('sharedb-mongo')(dbConfig.aloft);
var backend = ShareDB({db: db});
var connection = backend.connect();
var doc = connection.get(author, title);

doc.fetch(function(err) {
  if (err) throw err;
  doc.del(function(err) {
    if (err) throw err;
    // When done with the doc, remove the client's reference to the doc object so that it does not stay in memory:
    doc.destroy();
  });
});

Also note that if you don't need to wait for the delete to finish, you don't need to supply a callback. This will throw an exception if an error is returned on delete. You can also handle the 'error' event on the doc, which is a pattern with Node.js EventEmitters.

doc.fetch(function(err) {
  if (err) throw err;
  doc.del();
  doc.destroy();
});

--
You received this message because you are subscribed to the Google Groups "ShareJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sharejs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stanley Sakai

unread,
Jul 8, 2016, 7:11:18 PM7/8/16
to ShareJS
That did it! Thank you so much!
Reply all
Reply to author
Forward
0 new messages