3

With the RethinkDB JavaScript driver, is there a way to determine if there is another document available while within a "cursor.each" or a "cursor.on('data')" event?

Via each

cursor.each(function(err, doc) {
        if (err) throw err;

        // process document here
        // Is there a way to tell if there is another doc coming?

    }, function() {
        // End of data here, no document passed
    })
);

or via Event Emitter

cursor.on('data', function(doc) { 
    // handle doc, check if another doc is coming or not
});
cursor.on('end', function() { 
    // no document passed, just indicating end of data
})
Dustin Brownell
  • 817
  • 7
  • 10

2 Answers2

2

There are a couple of ways you could go about this. Keep in mind that these would only work if you're not currently in changefeed.

1. Using cursor.toArray()

You could first convert the cursor into an array and then just use the index to determine if there is another row on the cursor.

r 
  .table('hello')
  .filter({ name: 'jorge' })
  .run(conn)
  .then(function (cursor) {
    return cursor.toArray();
  })
  .then(function (array) {
     array.forEach(function (row, i) {
        if (i === array.length - 1) {
           // There are now more rows after this
        } else {
           // There are more rows
        }
     }); 
  });

As coffeemug mentioned above, this approach won't work for large datasets since converting the cursor into an array means that you have to load all the data.

2. Using cursor.next

A less convenient way of doing it, but probably more performant is to use cursor.next. The way this would work is that the .next method on the cursor would throw an error if there are no more rows in the cursor.

Your code would look something like this:

r
  .table('hello')
  .filter({ name: 'jorge' })
  .run(conn)
  .then(function (cursor) {
    var hasNextRow = function (cb, prevRow) {
      cursor.next(function (err, row) {
        if (err) cb(false, prevRow);
        if (row) cb(true, prevRow, row);
      })
    };
    var consoleRow = function (row) {
      hasNextRow(function (hasNextRow, prevRow, row) {
        if (prevRow) {
          if (!hasNextRow) console.log('isLast');
          // This is your row
          console.log(i, prevRow);
        }
        if (hasNextRow) {
          consoleRow(row);
        }
      }, row);
    };
    consoleRow();
  });

Basically, this code saves a reference to the last row and goes on to the next row. At that point, it'll know if the next row exists or not and you can handle any behavior on that row using the prevRow variable.

Jorge Silva
  • 4,574
  • 1
  • 23
  • 42
  • Thanks, I ended up using the next() functionality. For other reference, here is the official RethinkDB API doc http://rethinkdb.com/api/javascript/next/ – Dustin Brownell Apr 14 '15 at 19:35
0

The each cursor method is really meant to process the elements independently. If you need to do something more sophisticated, I'd suggest using next (http://rethinkdb.com/api/javascript/next/) -- see the examples for details on how to use the method.

If your dataset is short, you can also call cursor.toArray() and just get the array of elements.

coffeemug
  • 1,338
  • 11
  • 10