如何停止在 mongodb 集合中插入重复文档

Posted

技术标签:

【中文标题】如何停止在 mongodb 集合中插入重复文档【英文标题】:How to stop insertion of Duplicate documents in a mongodb collection 【发布时间】:2014-07-30 03:40:11 【问题描述】:

让我们有一个包含三个文档的MongoDB 集合..

db.collection.find()

  _id:'...', user: 'A', title: 'Physics',   Bank: 'Bank_A' 
  _id:'...', user: 'A', title: 'Chemistry', Bank: 'Bank_B' 
  _id:'...', user: 'B', title: 'Chemistry', Bank: 'Bank_A' 

我们有一个文档,

 doc =  user: 'B', title: 'Chemistry', Bank:'Bank_A' 

如果我们使用

 db.collection.insert(doc) 

在这里,这个重复的文档将被插入到数据库中。

  _id:'...', user: 'A', title: 'Physics',   Bank: 'Bank_A' 
  _id:'...', user: 'A', title: 'Chemistry', Bank: 'Bank_B' 
  _id:'...', user: 'B', title: 'Chemistry', Bank: 'Bank_A' 
  _id:'...', user: 'B', title: 'Chemistry', Bank: 'Bank_A' 

如何阻止这种重复。应该对哪个字段进行索引或任何其他方法?

【问题讨论】:

Mongodb avoid duplicate entries 的可能重复项 @John Petrone :在这里,我们不能对特定字段进行索引,因为字段的值是重复的。 unique:true 会产生问题。 使用复合索引docs.mongodb.org/manual/tutorial/create-a-compound-index 【参考方案1】:

您要查找的是AddToSet,而不是PushInsert。 使用 Upsert 标志似乎对我不起作用。

即:var updateSet = Builders<T>.Update.AddToSet(collectionField, value);

请注意,AddToSet 似乎在进行值比较。

【讨论】:

【参考方案2】:

也许这比其他方式慢一点,但它也有效。它可以在循环中使用:

db.collection.replaceOne(query, data, upsert: true)

查询可能是这样的:

 _id: '5f915390950f276680720b57' 

https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne

【讨论】:

【参考方案3】:

您应该在唯一标识 MongoDB 集合中的文档的字段集上使用复合索引。例如,如果您决定 user、title 和 Bank 的组合是您的唯一键,您将发出以下命令:

db.collection.createIndex(  user: 1, title: 1, Bank: 1 , unique:true )

请注意,这应该在您删除以前存储的重复项后完成。

http://docs.mongodb.org/manual/tutorial/create-a-compound-index/

http://docs.mongodb.org/manual/tutorial/create-a-unique-index/

【讨论】:

@Roberto ensureIndex 如果索引不存在则创建索引 哦,你是对的@Azmisov,但从 3.0 开始实际上已弃用 ensureIndex,现在它是 createIndex 的(已弃用)别名,因为创建此答案时不存在 3.0 我正在删除我的downvote :) (在编辑答案之前,它不允许我撤消我的 downvote,让我们希望 John Petrone 将其添加为更新...【参考方案4】:

已根据上述答案进行了更新。

请使用db.collection.updateOne() 而不是db.collection.update()。 还有db.collection.createIndexes() 而不是db.collection.ensureIndex()

更新: update() 和 ensureIndex() 方法已从 mongodb 2.* 中弃用,您可以在 mongo 中查看更多详细信息,路径为 ./mongodb/lib/collection.js。 对于update(),推荐方法为updateOne, updateMany, or bulkWrite。 对于ensureIndex(),推荐方法为createIndexes

【讨论】:

为什么应该首选这些选项?请详细说明你的答案。 据我所知,对于update,它只是重新设计了响应对象。【参考方案5】:

不要使用插入。

使用update with upsert=true。 Update 将查找与您的查询匹配的文档,然后它将修改您想要的字段,然后,如果没有文档与您的查询匹配,您可以告诉它 upsert:True 如果您想插入。

db.collection.update(
   <query>,
   <update>,
  
    upsert: <boolean>,
     multi: <boolean>,
    writeConcern: <document>
   
  )

因此,对于您的示例,您可以使用如下内容:

db.collection.update(doc, doc, upsert:true)

【讨论】:

请注意,如果您希望为第一次使用准备文档,则 upsert 可能很危险,因为它会很高兴地清除存储在那里的所有内容,以支持 upsert 值。 John P. 提出的模式是避免重复记录的更好的通用答案,尽管对于复合键将包含所有现有文档字段的简单情况,这两种方法都足够了。如果您考虑为记录添加非常常见的“创建时间”,您可以看到这在许多一般情况下是如何分解的...... 我恳请大家也参考 John Petrone 的回答!!

以上是关于如何停止在 mongodb 集合中插入重复文档的主要内容,如果未能解决你的问题,请参考以下文章

mongodb怎么插入多个文档

MongoDB 插入文档

mongodb使用map reduce从其他集合中插入嵌入文档海量集合

MongoDB Scala - 删除集合中的重复文档

Mongodb Lookup 无法正常工作

运行MongoDB查询以更新循环中的序列字段