M.omer
M.omer

Reputation: 23

Python mongodb error with email as unique key

I have a collection with Username, Password and Email, so I created a unique index with pymongo in python :

import pymongo 

info.create_index( [("Username", pymongo.TEXT), ("Email", pymongo.TEXT)],unique=True)

first insert:

mydict = { "Username": "userA","Email": "[email protected]"}
mycol.insert_one(mydict)

second insert:

mydict = { "Username": "userB","Email": "[email protected]"}
mycol.insert_one(mydict)

But when I test it with a second insert it throws this exception:

pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: users.info index: Username_text_Email_text dup key: { : "com", : 0.6666666666666666 }

am I missing something here?

Upvotes: 1

Views: 1856

Answers (2)

Imran
Imran

Reputation: 6235

The issue is with your index creation on email field. After looking at this SO Post, you need to create the email index with pymongo.ASCENDING option instead of pymongo.TEXT.

So, it will be something like this.

info.create_index( [("Username", pymongo.TEXT), ("Email", pymongo.ASCENDING)],unique=True)

Also, it is always better to clear the dict object before reusing it since pymongo is adding _id field to the document before inserting it and might cause unnecessary conflict issues.

mydict = { "Username": "userA","Email": "[email protected]"}
mycol.insert_one(mydict)
<pymongo.results.InsertOneResult object at 0x1086c7bc8>
mydict
{'Username': 'userA', 'Email': '[email protected]', '_id': ObjectId('5d5dfd90337d3d79a9bf1da8')}
mydict.clear()
mydict = { "Username": "userB","Email": "[email protected]"}
mycol.insert_one(mydict)
<pymongo.results.InsertOneResult object at 0x1086c7e48>

Update -

When you create one single compound index with both fields(given in your question) and asking uniqueness, you are asking that the combination of both fields data should always be unique(not the individual fields data).

So, according to mongo, below inserts are valid and not duplicate since combination is unique.

{ "Username": "userA","Email": "[email protected]"}
{ "Username": "userB","Email": "[email protected]"}

If your requirement is that UserName should not repeat more than once and Email field should not repeat more than once then separate individual indexes are fine(given in your answer).

First, get your requirement correct then create the indexes accordingly. Also, your answer has indexes not created with pymongo.TEXT option and that's why you were able make 2 inserts with different email but if you create the Email index with TEXT option then you won't be able to insert emailA & emailB.

Here is SO POST which will give little bit idea on difference between TEXT indexes vs Normal Indexes. https://stackoverflow.com/a/24316510/5030709

Upvotes: 2

M.omer
M.omer

Reputation: 23

Ok I solved it (Don't know why it works... But it works):

I changed index creation: Instead of:

import pymongo 

info.create_index( [("Username", pymongo.TEXT), ("Email", pymongo.TEXT)],unique=True)

I did:

import pymongo

mycol.create_index( "Username",unique=True)
mycol.create_index( "Email",unique=True)

if someone know why it works.. enlighten me please :)

Upvotes: 1

Related Questions