1

I have a table of 'words', and what I want to do is, if a user uses that word, insert it into the table. But, if it already exists, update the count on that word.

I don't see a way to actually set columns as unique.. That said, how do I avoid the race condition:

t1 - user1 checks if 'Love' is used. NO t2 - user2 checks if 'Love' is used. NO t3 - user1 adds 'Love' t4 - user2 adds 'Love'

I do not want this to be in the database twice. Anyway to accomplish this in Parse?

JP.
  • 544
  • 5
  • 20

2 Answers2

5

To avoid race conditions, you should make the column/field unique. Do that in the database that you use with with Parse (if you use mongoDB with your parse server, then here's a link for mongoDB for example - https://docs.mongodb.com/manual/core/index-unique/). Then in CloudCode - try to create a new word object and store it. If the word already exists, the store will fail and then you can use a query to find the existing word and increment instead.

Evtim Georgiev
  • 444
  • 4
  • 10
1

You can use the 'exists' query to check for objects which have the key set:

var Word = Parse.Object.extend("words");
var query = new Parse.Query(Word);
query.exists("Love");
query.find({
  success: function(results) {
    if(results.length === 0){
      // Insert a new word object with the 'Love' key set to 1
      var newWord = new Word();
      newWord.set('Love', 1);
      newWord.save(null, {
        success: function(newWord) {
          alert('New object created with objectId: ' + newWord.id);
        },
        error: function(newWord, error) {
          alert('Failed to create new object, with error code: ' + error.description);
        }
      });
    } else {
      // Get the existing word object and increment its 'Love' key by 1
      var existingWord = results[0];
      var currCount = existingWord.get('Love');
      existingWord.set('Love', currCount + 1);
      existingWord.save(null, {
        success: function(existingWord) {
          alert('Existing object saved with objectId: ' + newWord.id);
        },
        error: function(existingWord, error) {
          alert('Failed to save existing object, with error code: ' + error.description);
        }
      });
    }
  },
  error: function(error) {
    alert("Error: " + error.code + " " + error.message);
  }
});

With regard to preventing race conditions, you could handle this with Parse Cloud Code. You could have a Cloud Function which handles the input of the data and it should handle the requests sequentially.

Daniel Bank
  • 3,581
  • 3
  • 39
  • 50
  • 1
    this answer looks right. why hasnt it been marked correct? Did it solve your problem @JP? – Zen May 16 '14 at 15:43
  • in the code, there is an extra equal sign in `if(results.length === 0)` – Mahir Aug 13 '14 at 09:05
  • 1
    Yes, in JavaScript === compares the value and type. See this SO question: http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons – Daniel Bank Aug 13 '14 at 17:52
  • 1
    This code doesn't work if more than one requests executed concurrently. – Arsenius Jul 03 '17 at 09:40
  • The check routine must be in the server side, not in the client side. I think the best solution is to use **CloudCode** or **Database UNIQUE KEY** to prevent saving duplicates. – Nadjib Rebahi Nov 25 '21 at 07:59