Yordy Mora
Yordy Mora

Reputation: 49

How can I avoid duplicate data in Firebase / Cloud Firestore

I'm making a web page, but when entering the same ID an error should come out, but I have not been able to do it.

 function save () {
    if (validate  = true) {
        console.log("exists!")
    }else {
        
    var imei = document.getElementById('imei').value;
    var marca = document.getElementById('marca').value;
    var referencia = document.getElementById('referencia').value;
    var precio = document.getElementById('precio').value;

    db.collection("phone").add({
        Imei: imei,
        Marca: marca,
        Referencia: referencia,
        Precio: precio
    })
        .then(function (docRef) {
            document.getElementById('imei').value = '';
            document.getElementById('marca').value = '';
            document.getElementById('referencia').value = '';
            document.getElementById('precio').value = '';
        })
        .catch(function (error) {
            window.alert("Error adding document: ", error);
        });
    }
}save();

function validate () {
    firebase.database().ref(`phone/${Imei}/imei`).once("value", snapshot => 
    { const imei = snapshot.val(); 
        if (imei){ 
            console.log("user exists!"); 
        } 
    }); 
}

If you can tell me where I have the error, or the best solution I would really appreciate it

Upvotes: 0

Views: 525

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598857

A few problems with your code:

  1. You're building the path with phone/${Imei}/imei, but your variable name is spelled imei (and not Imei). Case matter in JavaScript, as it does in most programming languages, so I recommend paying close attention to spelling and case.
  2. You're not calling validate() anywhere, which means your check doesn't run.
  3. You're not returning anything from validate(). And since what you want to return comes from the database in an asynchronous call, you can only return it with a promise or async / await. This aslome could warrant its own answer, so I recommend you study Firebase, retrieving data asynchronously, How to return values from async functions using async-await from function? and How to return value from an asynchronous callback function?
  4. You really should use a transaction to ensure no-one may claim the IMEI between the read and write operation in your code.
  5. If the IMEI value should be unique, it is better to use that as the key instead of as a property value. Read more on that here:

Combining all these, a better implementation might look something like:

function save () {
    var imei = document.getElementById('imei').value;
    var marca = document.getElementById('marca').value;
    var referencia = document.getElementById('referencia').value;
    var precio = document.getElementById('precio').value;

    var imeiDocRef = db.collection("phone").doc(imei);

    db.runTransaction(function(transaction) {
        // This code may get re-run multiple times if there are conflicts.
        return transaction.get(imeiDocRef).then(function(imeiDoc) {
            if (imeiDoc.exists) {
                throw `IMEI '${imei}' already exist!`;
            }

            transaction.set(imeiDocRef, { 
                Imei: imei,
                Marca: marca,
                Referencia: referencia,
                Precio: precio
            });
        });
    }).then(function() {
        console.log("Transaction successfully committed!");
        document.getElementById('imei').value = '';
        document.getElementById('marca').value = '';
        document.getElementById('referencia').value = '';
        document.getElementById('precio').value = '';
    }).catch(function(error) {
        console.log("Transaction failed: ", error);
    });
}

Upvotes: 1

Related Questions