Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase how to prevent duplicate entries atomically

I'm looking at using firebase as a data store for user data for a web app. My current thought is to store each user's data using the timestamp of when they joined as the key referencing that user's data. The advantage of this scheme is that it's a simple way to assign unique integer ids to users, and makes chronological sorting of users simple.

A downside, however, is that if two add user requests are submitted with identical data, the app will happily add two separate entries, which is unideal. I could shuffle things around (I'm starting to think I should use email as the key and prioritize by join data, rather than my current scheme), but suppose I don't want to. Is there any way to prevent duplicate data?

The naive approach would probably be just to do something like:

if(!searchFirebaseForUser(data)) {
    addUser(data);
}

But this is definitely a race condition; it'd be easy for two requests to both query and find no user in the database, and both add. I'd like to do this in a transaction, but it doesn't seem like the Firebase transaction support covers this case. Is there any way to handle this?

like image 640
Retsam Avatar asked Sep 01 '13 02:09

Retsam


People also ask

How do you prevent duplicate data entry for two fields?

You can prevent duplicate values in a field in an Access table by creating a unique index. A unique index is an index that requires that each value of the indexed field is unique.


1 Answers

You will probably have to use the username or email address as a key, and try to atomically write to that location.

Here is the relevant code sample from the transaction function reference. In this case, we use wilma as the key for the user.

// Try to create a user for wilma, but only if the user id 'wilma' isn't already taken.
var wilmaRef = new Firebase('https://SampleChat.firebaseIO-demo.com/users/wilma');
wilmaRef.transaction(function(currentData) {
  if (currentData === null) {
    return {name: {first: 'Wilma', last: 'Flintstone'} };
  } else {
    console.log('User wilma already exists.');
    return; // Abort the transaction.
  }
}, function(error, committed, snapshot) {
  if (error)
    console.log('Transaction failed abnormally!', error);
  else if (!committed)
    console.log('We aborted the transaction (because wilma already exists).');
  else
    console.log('User wilma added!');
  console.log('Wilma\'s data: ', snapshot.val());
});
like image 151
Jo Liss Avatar answered Sep 29 '22 04:09

Jo Liss