【问题标题】:How to stop insertion of Duplicate documents in a mongodb collection如何停止在 mongodb 集合中插入重复文档
【发布时间】: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 mongodb-query database nosql


【解决方案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 的回答!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      • 2020-08-17
      • 2018-04-11
      • 2016-09-22
      • 1970-01-01
      相关资源
      最近更新 更多