简体   繁体   中英

Adding documents to Firestore with a field that must be unique

Assume two users on different devices are performing following operation at the same time.

user one:

db.collection('agents').where('phone','==','9876543210')
  .get()
  .then(function(querySnapshot) {
        let agents = [];
        querySnapshot.forEach(function(doc) {
            agents.push(doc.data());
        });

        if(agents.length > 0){
          agentExists();
        }
        else{
          db.collection('agents').add({
            firstName: "ABC",
            lastName: "XYZ",
            phone: "9876543210"
          })
          .then(function(){
             agentAdded();
          });
        }
  })
  .catch(function(err){
     console.log(err);
  });

user two:

db.collection('agents').where('phone','==','9876543210')
  .get()
  .then(function(querySnapshot) {
        let agents = [];
        querySnapshot.forEach(function(doc) {
            agents.push(doc.data());
        });

        if(agents.length > 0){
          agentExists();
        }
        else{
          db.collection('agents').add({
            firstName: "MNO",
            lastName: "PQR",
            phone: "9876543210"
          })
          .then(function(){
             agentAdded();
          });
        }
  })
  .catch(function(err){
     console.log(err);
  });

where users are trying to add agent information with different firstName and lastName but same phone number, and the code is written in such a way that first query searches for the number, if it exists the agent is not added in the collection, if it doesn't then it is added. But when both the users perform above operations at the same time, both the agents are added, whereas my requirement is to allow only one agent to get added as the phone number will be duplicated then.

Other solutions tried: Tried using onSnapshot() method, to get realtime updates, but as we know firestore sdk first adds the document in cache then to backend, so when a new agent is added, first it shows agent exits and then shows agent added.

In this case, since the phone number must (apparently) be unique in this collection, it should also be the document ID. If you use the phone number as the document ID, then you can use a transaction to ensure that only one client can create that document, in order to avoid a race condition.

If you don't use the phone number as the document ID, I don't think there's a way you can ensure the uniqueness of the phone number as an ordinary field, as Firestore doesn't offer a way to perform a transaction on the results of an arbitrary query.

If you can't use the phone number as the document ID, then you will need a way to clean up any duplicates, perhaps using a server timestamp to determine which one was added last.

If you don't want to keep the phone number as key then you should use transactions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM