-1

So in my realtime database it would look like:

ss: {
  xx: {
    id: 1
  },
  yy: {
    id: 2
  },
  ...
}

I tried to first get child with largest ID FirebaseRef.child('ss').orderByChild('id').limitToLast(1) and then do +1 for retrieved value.. then push new record with that. But that could result doubling id's, as between the fetch and the push, someone else can make a new record. I looked into transaction feature, but could not figure out have to use that in my scenario (as it retrieves and updates only values?).

trshmanx
  • 600
  • 7
  • 16
  • I've never looked into Firebase, but does it support sequences? Normal RDBMSes usually have this - it's basically something that gives you incrementing (or otherwise defined) numbers for use as IDs. The DB handles this automatically on insert, so you never need to handle it manually. – VLAZ Jan 05 '20 at 20:13
  • Could not find anything on that. That's why I'm asking here. Thank you. – trshmanx Jan 05 '20 at 20:14
  • 2
    Also see: https://stackoverflow.com/a/47653231, https://stackoverflow.com/a/39065899, https://stackoverflow.com/a/36682658, https://stackoverflow.com/a/58050877 – Frank van Puffelen Jan 05 '20 at 21:57

1 Answers1

1

One possible approach is to maintain a counter and each time you need to generate a new id, increment this counter in a transaction and read the value:

The following should do the trick:

  //Declare a function that increment a counter in a transaction
  function getId() {
    var counterRef = firebase.database().ref('counter');
    return counterRef.transaction(function(currentId) {
      return currentId + 1;
    });
  }


  //Call the asynchronous getID() function
  getId().then(function(transactionResult) {
    var newId = transactionResult.snapshot.val();
    console.log(newId);
    firebase.database().ref('ss/xx').set({id: newId});
  });

You don't need to create the counter node, it will be automatically created with the first call to the getId() function.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • Are you sure `return currentId + 1;` is enough in the absence of a counter? I'd usually do `return (currentId || 0) + 1;`. – Frank van Puffelen Jan 05 '20 at 21:57
  • @FrankvanPuffelen It is done this way in the example from the [documentation](https://firebase.google.com/docs/reference/js/firebase.database.Reference?authuser=2#transaction) and it is expressly mentioned "// If users/ada/rank has never been set, currentRank will be `null`". – Renaud Tarnec Jan 05 '20 at 22:00
  • 1
    That part I know. But I never realized that `null + 1 = 1`. Oh JavaScript, you wonderful beast. :-D – Frank van Puffelen Jan 05 '20 at 22:04
  • 1
    `true + null = 1` is also an "interesting" one... :-) – Renaud Tarnec Jan 05 '20 at 22:08