MongoDB:是否删除基于ObjectId的重复文档?

MongoDB:是否删除基于ObjectId的重复文档?,mongodb,Mongodb,这确实是一个悬而未决的问题。我很抱歉,如果这有点含糊不清,但我试图收集其他人的想法,因为我是非常新的蒙哥 处境 我意识到我的收藏有多个重复文档(基于名称键) 这些文档可能是相同的,或者可能在文件的后续转储过程中被更改(我们希望保留以后的更改) 因为并没有插入日期,所以在查看文档时很难判断哪一个是最新的(糟糕的模式设计) 受通缉的 删除先前插入的文档的步骤 我读到集合中的每个文档都被分配了一个ObjectId(),使文档具有唯一性 问题: 是否可以根据ObjectId知道较早插入的文档,

这确实是一个悬而未决的问题。我很抱歉,如果这有点含糊不清,但我试图收集其他人的想法,因为我是非常新的蒙哥

处境
  • 我意识到我的收藏有多个重复文档(基于名称键)
  • 这些文档
    可能是相同的
    ,或者
    可能在文件的后续转储过程中被更改
    (我们希望保留以后的更改)
  • 因为并没有插入日期,所以在查看文档时很难判断哪一个是最新的(糟糕的模式设计)
受通缉的
  • 删除先前插入的文档的步骤
  • 我读到集合中的每个文档都被分配了一个
    ObjectId
    (),使文档具有唯一性
问题:
  • 是否可以根据ObjectId知道较早插入的文档,并使用
    Map Reduce
    将其删除
  • 还有其他想法和建议吗

好的,因为对象id使用时间戳,因为它的前导是四个字节,所以您可以通过一点数学来完成这项工作

谢天谢地,mongo shell有一种从对象id获取时间戳的方法,您需要执行更多的javascript来首先查询具有相同名称的文档,然后将它们存储在临时变量(如果使用命令行)或临时表(如果使用驱动程序)中并使用下面的链接中显示的时间戳getter解析每个id

请记住,对象id仅精确到秒,因此这在快速插入模式下仍然没有帮助

但无论哪种方式,您所要求的都是可行的,无论是在map-reduce函数中,还是在上面所示的通过命令行实现的方式中


试试看,如果你被卡住了,告诉我。如果我知道你的收藏结构,我可能会很快想出一些东西,但只有在你把头撞上几下之后:)

今晚我很无聊,所以我们开始吧

第一步。让我们准备测试数据。 第二步。地图缩小了 它基本上按名称对所有文档进行分组,然后选择id最大的文档

第三步。用唯一的数据做一些事情。 例如,删除原始集合,迭代此集合并将值插入新集合。完成后,不要忘记删除临时收集

重要的
我没有从objectid中提取时间戳,因为我假设您不会每秒运行导入作业两次(甚至可能不是每秒钟)。

给定一个文档,您如何判断它是另一个文档的版本还是一个全新的文档?我不能,如果有多个文档具有相同的
name
keyseems您喜欢这个问题:)我想我知道解决方案。等等,我刚刚意识到这张海报也使用了Mongo的扩展JSON支持。我仍然认为我的方法更简单,但这也是一个优雅的解决方案。是否有必要从ObjectID中提取日期?为什么不直接比较ObjectID(或者在这个_id字段上对查询排序)?插入时间越晚,ObjectID越大。问题:id会一直增加吗?给定对象Id由时间、机器、pid、inc组成,除机器之外的所有对象都会增加,但机器?@daydreamer:除非你弄乱了系统时钟,那么是的,它肯定是单调增加的。听起来不错,有没有任何参考文档证明这一点?我会尝试使用你的技巧,然后会回复你,非常感谢你的帮助看看@Prasith的答案。ObjectId包含时间戳,它占用最高的4个字节。及
> db.users.insert({name: 'John', other_field: Math.random()})
> db.users.insert({name: 'Bob', other_field: Math.random()})
> db.users.insert({name: 'Mary', other_field: Math.random()})
> db.users.insert({name: 'John', other_field: Math.random()})
> db.users.insert({name: 'Jeff', other_field: Math.random()})
> db.users.insert({name: 'Ivan', other_field: Math.random()})
> db.users.insert({name: 'Mary', other_field: Math.random()})
> db.users.find()
{
    "_id" : ObjectId("501976e9bee9b253265bba8b"),
    "name" : "John",
    "other_field" : 0.9884713875252772
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8c"),
    "name" : "Bob",
    "other_field" : 0.048004131996396415
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8d"),
    "name" : "Mary",
    "other_field" : 0.20415803582615222
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8e"),
    "name" : "John",
    "other_field" : 0.5514446987265585
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8f"),
    "name" : "Jeff",
    "other_field" : 0.8685077449753242
}
{
    "_id" : ObjectId("501976e9bee9b253265bba90"),
    "name" : "Ivan",
    "other_field" : 0.2842514340422925
}
{
    "_id" : ObjectId("501976eabee9b253265bba91"),
    "name" : "Mary",
    "other_field" : 0.984048520281136
}
var map = function() {
  emit(this.name, this);
};

var reduce = function(name, vals) {
  var last_obj = null;
  vals.forEach(function(v) {
    if(!last_obj || v._id > last_obj._id) {
      last_obj = v;
    }
  });
  return last_obj;
};

db.users.mapReduce(map, reduce, {out: 'temp_coll'})
> db.temp_coll.find()
{
    "_id" : "Bob",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba8c"),
        "name" : "Bob",
        "other_field" : 0.048004131996396415
    }
}
{
    "_id" : "Ivan",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba90"),
        "name" : "Ivan",
        "other_field" : 0.2842514340422925
    }
}
{
    "_id" : "Jeff",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba8f"),
        "name" : "Jeff",
        "other_field" : 0.8685077449753242
    }
}
{
    "_id" : "John",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba8e"),
        "name" : "John",
        "other_field" : 0.5514446987265585
    }
}
{
    "_id" : "Mary",
    "value" : {
        "_id" : ObjectId("501976eabee9b253265bba91"),
        "name" : "Mary",
        "other_field" : 0.984048520281136
    }
}