【问题标题】:Python mongodb error with email as unique key将电子邮件作为唯一键的 Python mongodb 错误
【发布时间】:2019-12-27 05:05:07
【问题描述】:

我有一个包含用户名、密码和电子邮件的集合,所以我在 python 中使用 pymongo 创建了一个唯一索引:

import pymongo 

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

第一次插入:

mydict = { "Username": "userA","Email": "emailA@example.com"}
mycol.insert_one(mydict)

第二次插入:

mydict = { "Username": "userB","Email": "emailB@example.com"}
mycol.insert_one(mydict)

但是当我用第二次插入测试它时,它会抛出这个异常:

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

我错过了什么吗?

【问题讨论】:

  • 我认为这是stackoverflow.com/q/36649794/4711785的类似问题
  • 你的两个插入是什么?他们是相同的用户名+电子邮件组合吗?如果是这样,那么这种行为是预期的,因为用户名+电子邮件的组合对于该集合中的每个文档都必须是唯一的。如果写入会导致冲突,则会抛出异常,如您在此处所见。如果您不希望程序崩溃,请务必将您的插入内容包装在 try/catch 块中并相应地处理异常。
  • @B.弗莱明对不起,我不清楚,我的第一个插入是例如 Username: userA 和 Email: EmailA@example.com ,当我插入 Username: userB 和 Email:EmailB@example.com 时,它会抛出该异常
  • 我建议检查该用户当前是否存在并从那里开始。

标签: mongodb pymongo unique-index


【解决方案1】:

问题在于您在 email 字段上创建索引。查看this SO Post 后,您需要使用pymongo.ASCENDING 选项而不是pymongo.TEXT 创建email 索引。

所以,它会是这样的。

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

此外,在重新使用它之前最好 clear dict 对象,因为 pymongo 在插入之前将 _id 字段添加到文档中,并且可能会导致不必要的冲突问题。

mydict = { "Username": "userA","Email": "emailA@example.com"}
mycol.insert_one(mydict)
<pymongo.results.InsertOneResult object at 0x1086c7bc8>
mydict
{'Username': 'userA', 'Email': 'emailA@example.com', '_id': ObjectId('5d5dfd90337d3d79a9bf1da8')}
mydict.clear()
mydict = { "Username": "userB","Email": "emailB@example.com"}
mycol.insert_one(mydict)
<pymongo.results.InsertOneResult object at 0x1086c7e48>

更新 -

当您创建一个包含两个字段(在您的问题中给出)并询问唯一性的复合索引时,您要求两个字段数据的组合应该始终是唯一的(而不是单个字段数据)。

因此,根据 mongo,下面的插入是有效的并且不重复,因为组合是唯一的。

{ "用户名": "userA","Email": "emailA@example.com"}
{ "用户名": "userB","Email": "emailA@example.com"}

如果您的要求是 UserName 不应重复多次,Email 字段不应重复多次,则单独的单独索引是可以的(在您的答案中给出)。

首先,让您的要求正确,然后相应地创建索引。此外,您的答案具有未使用 pymongo.TEXT 选项创建的索引,这就是为什么您可以使用不同的电子邮件进行 2 次插入,但如果您使用 TEXT 选项创建电子邮件索引,那么您将无法插入 emailA 和 emailB。

这是 SO POST,它可以让您了解 TEXT 索引与普通索引之间的差异。 https://stackoverflow.com/a/24316510/5030709

【讨论】:

  • 我尝试了这个解决方案,但不知何故 monogodb 不断添加重复值......“用户名”工作正常,但“电子邮件”有问题
  • 你能提供插入重复数据的地方吗?
  • 例如,如果我的第一个插入是:mydict = { "Username": "userA","Email": "emailA@example.com"} 而我的第二个插入是:mydict = { "Username ": "userB","Email": "emailA@example.com"} 它将被存储
  • @M.omer 检查我更新的答案。在您提出最初的问题后,您的要求似乎发生了变化。
【解决方案2】:

好的,我解决了(不知道为什么会这样……但确实有效):

我更改了索引创建: 而不是:

import pymongo 

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

我做到了:

import pymongo

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

如果有人知道它为什么起作用..请赐教:)

【讨论】:

  • 好的,这是 2 个单独的唯一索引,可能适合您的需要。如果您曾经使用 mongodb 索引获得“第一个有效但第二个无效”,那么几乎可以肯定您的字段与您的键不匹配。第一个有效,因为它实际上是“空白”,第二个失败,因为你不能有重复的空白。
猜你喜欢
  • 2019-02-25
  • 2012-04-06
  • 2014-04-29
  • 2020-12-03
  • 2015-04-15
  • 2015-03-02
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多