2

I want to insert a record in MongoDB database but only if it does not exist there yet. Something tells me that this code is not optimal in terms of performance:

if db.foo.find(record).count() == 0:
    db.foo.insert(record)

How to do it fastest way?

Community
  • 1
  • 1
Inspiring
  • 41
  • 1
  • 5

2 Answers2

7

When update, use upsert flag:

db.foo.update_one(filter, updates_dict, upsert=True)

Working exemple:

db.things.update_one({'thing':'apple'}, {'$set':{'color':'red'}}, upsert=True)

This will search for the firts document with 'thing': 'apple' and update its color to red. If no document are found, it will create one with those two parameters.

See docs: http://api.mongodb.org/python/current/index.html

Tales Pádua
  • 1,331
  • 1
  • 16
  • 36
  • Thanks but I get: File "foo.py", line 35, in db.foo.update(record, upsert=True) TypeError: update() takes at least 3 arguments (3 given) – Inspiring Mar 16 '16 at 13:55
  • update is deprecated, I will edit to update_one – Tales Pádua Mar 16 '16 at 13:58
  • Let's imagine I am not a human but a preprocessor. How db.foo.insert(record) translates into db.foo.update_one(filter, record, upsert=True)? What is filter? – Inspiring Mar 16 '16 at 14:06
  • According to the docs: filter: A query that matches the document to update. – Tales Pádua Mar 16 '16 at 14:09
  • You should read the docs: https://api.mongodb.org/python/current/api/pymongo/collection.html?highlight=update_one#pymongo.collection.Collection.update_one – Tales Pádua Mar 16 '16 at 14:09
  • 2
    Thank you for your answer but then why not to answer to any question on stackoverflow "you should read the docs $url_doc(technology)"? If I could have found the answer to my question in documentation, I would not have asked it here. – Inspiring Mar 16 '16 at 14:19
  • Sorry, but I did answered both of your questions. Although it is always good to questions on stackoverflow, you will learn much more when you start to read and understand documentations, and I am just encouraging it. The answer of your questions are easily found in the docs. As for how insert translate to update_one, I am not quite sure what is your question here – Tales Pádua Mar 16 '16 at 14:25
  • If you have a __working__ replacement for the code in my original question please just provide it here. Thank you. – Inspiring Mar 16 '16 at 14:44
  • Edited with a working example – Tales Pádua Mar 16 '16 at 14:51
  • You probably want to add that update_one is also an atomic operation, whereas the find+insert operation is sensitive to race conditions. – Derick Mar 16 '16 at 15:16
  • Thanks but example is still not quite what I expected. There are no apples and colour, only 'record'. Please update. – Inspiring Mar 16 '16 at 15:32
  • You are not making any sense. Every information you need is there. It is already ansered. If you want me to adapt to your example, I need to know what this 'record' object is and what variables of this object you are trying to create/update – Tales Pádua Mar 16 '16 at 15:44
  • If you claim your example is an equivalent of my original code why would you need to know what is in **record**? – Inspiring Mar 16 '16 at 16:05
  • Think this way: In your code, you check if there are any document using the `find` method. Find method receives a filter as a parameter, and `record`is your filter. This filter should be something, and in my answer, the filter is `'thing': 'apple'`. Then you use `insert`. Insert doesn't receive a filter, it receives the document itself, the key:values pair of your document, but you are passing the same `record` object for both methods. I dont claim my exemple is equivalent to your original code because I don't know know what filter you are applying, and what is the content of your object – Tales Pádua Mar 16 '16 at 16:42
  • Your example code is wrong. You are passing the same object to methods that expects different things. That's why I think you should read the docs, as you are not understanding basic concepts here. – Tales Pádua Mar 16 '16 at 16:53
  • Stackoverflow is a new (and only) documentation but you don't seem to be the best person to contribute into it. What I expected from you (instead of a personal attack) is db.foo.update_one(record, {'$set': record}, upsert=True) – Inspiring Mar 17 '16 at 09:55
  • Good you found your answer. Sorry you feel that way. I didn't attack you at all, I just gave you a very importante tip: learn to read the docs – Tales Pádua Mar 17 '16 at 12:23
0

If you just want to make sure that only one record can exist based on particular key, then create a unique index on that key. This will ensure uniqueness. Any attempt to inset a record with same key will fail. Your key can be e.g SSN.

Saleem
  • 8,728
  • 2
  • 20
  • 34