消除MongoDB中具有特定排序的重复项

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消除MongoDB中具有特定排序的重复项相关的知识,希望对你有一定的参考价值。

我有一个由与工作合同相对应的条目组成的数据库。在MongoDB数据库中,我是由特定工作人员聚合而成的,那么数据库(简化版本)看起来像这样。


    "_id" : ObjectId("5ea995662a40c63b14266071"),
    "worker" : "1070",
    "employer" : "2116096",
    "start" : ISODate("2018-01-11T01:00:00.000+01:00"),
    "ord_id" : 0
,

    "_id" : ObjectId("5ea995662a40c63b14266071"),
    "worker" : "1070",
    "employer" : "2116096",
    "start" : ISODate("2018-01-11T01:00:00.000+01:00"),
    "ord_id" : 1
,

    "_id" : ObjectId("5ea995662a40c63b14266072"),
    "worker" : "1071",
    "employer" : "2116055",
    "start" : ISODate("2019-01-03T01:00:00.000+01:00"),
    "ord_id" : 2
,

    "_id" : ObjectId("5ea995662a40c63b14266072"),
    "worker" : "1071",
    "employer" : "2116056",
    "start" : ISODate("2019-01-03T01:00:00.000+01:00"),
    "ord_id" : 3
,

我已根据工作人员重新安排


    "_id" : ObjectId("5ea995662a40c63b14266071"),
    "worker" : "1070",
    "contratcs" : [
             
               "employer" : "2116096",
               "start" : ISODate("2018-01-11T01:00:00.000+01:00"),
               "ord_id" : 0
             ,
             
               "employer" : "2116096",  
               "start" : ISODate("2018-01-11T01:00:00.000+01:00"),
               "ord_id" : 1
              // Since employer identification and starting date is the same of the previous, this is a duplicate!
         ]
,

    "_id" : ObjectId("5ea995662a40c63b14266072"),
    "worker" : "1701",
    "contratcs" : [
             
               "employer" : "2116055",
               "start" : ISODate("2019-01-03T01:00:00.000+01:00"),
               "ord_id" : 2
             ,
             
               "employer" : "2116056",
               "start" : ISODate("2019-01-04T01:00:00.000+01:00"),
               "ord_id" : 3
             
         ]

从原始表中对某些合同进行了仔细检查,因此我只需要保留一个。更具体地说(在该示例中),我考虑重复同一天与同一雇主签订的(同一工人)合同。但是,应该正确选择哪些副本保留,哪些不保留(这不取决于我)。实质上,存在一个名为“ ord_id”的字段(我已经生成了将数据库生成到MongoDB中的字段),该字段是一个数字并且是唯一的(因此,在重复项中,它是唯一实际不同的术语)。基本上,我必须在重复项中保留值最高的“ ord_id”。通过遵循this线程,我写道:

db.mycollection.aggregate([
     $unwind: "$contracts" ,
     $group: 
        _id:  WORKER: "$worker", START: "$contracts.start" ,
        dups:  $addToSet: "$_id" ,
        ord_id:  $addToSet: "$contracts.ord_id" ,
        count:  $sum: 1 
        
    ,
     $match:  count:  $gt: 1  ,
     $sort: count: -1, ord_id: -1  
],allowDiskUse: true).
forEach(function(doc) 
    doc.dups.shift();     
    db.mycollection.remove(_id : $in: doc.dups );  
);

尽管我在按合同进行汇​​总时面临消除淘汰的问题,但我想转移(然后保留)重复项中具有最高“ ord_id”值的重复项。我仍然是MongoDB的新手,并且仍处于从主要是关系(SQL)方法的思维转变阶段。对这个愚蠢的问题表示歉意。

答案

如果按ord_id进行反向排序,则可以在$first阶段使用$group选择最大值。此示例将返回doc中的整个文档以及重复的计数:

db.mycollection.aggregate([
     $unwind: "$contracts" ,
     $sort: "$contracts.ord_id":-1,
     $group: 
        _id:  WORKER: "$worker", START: "$contracts.start", EMPLOYER: "$contracts.employer" ,
        doc:  $first: "$$ROOT" ,
        count:  $sum: 1 
    
],allowDiskUse: true)
另一答案

此聚合将返回期望的结果-消除基于worker + employer + start contracts的重复项,并且仅保留(重复项中)具有最高ord_id的合同。

db.collection.aggregate( [
   
      $unwind: "$contracts" 
  ,
   
      $group:  
           _id:  worker: "$worker", employer: "$contracts.employer", start: "$contracts.start" ,
           max_ord:  $max: "$contracts.ord_id" ,
           doc:  $first: "$$ROOT" 
       
  ,
   
      $group: 
          _id:  _id: "$doc._id", worker: "$doc.worker" ,
          contracts:  $push:  employer: "$_id.employer", start: "$_id.start", ord_id: "$ords"  
      
  ,
   
      $addFields: 
          _id: "$_id._id", 
          worker: "$_id.worker"
      
   
] )

以上是关于消除MongoDB中具有特定排序的重复项的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:仅检索特定记录[重复]

如何删除 MongoDb 中的重复项?

如何在 MongoDB 中保留重复项的同时进行递归查找

MongoDb:查找具有重复项的精确数组匹配

使用谓词对核心数据进行排序以消除重复

如何在 Mongo db 上按 Java 文本搜索 [重复]