mongoDB 多字段条件分组匹配删除多余数据,并只保留最大值

为了以后自己不会忘记这个执行脚本是什么逻辑,决定写个帖子记录一下。
参考的帖子为:https://blog.csdn.net/haoyuexihuai/article/details/100084075
在此感谢以上帖子作者大佬的分享~~

db.getCollection('ts_data_i').aggregate(
[
//$match 即为筛选条件
//相当于 where time like '%2020-02-19%' and tagCode = 'v0406'
{$match :{
          time:/^2020-02-19/,
          "tagCode" : "v0496"
          }
},

//$group 即为分组条件
//相当于 select time,tagCode,deviceId,max(value) from 表名 group by time,tagCode,deviceId
//$group只会返回参与分组的字段,使用$addToSet在返回结果数组中增加_id字段
{$group : 
    {   _id : {
        'time': '$time',
        'tagCode': '$tagCode',
        'deviceId': '$deviceId'
        },
        value : {$max : "$value"},
        
        'uniqueIds': {
          '$addToSet': '$_id'
        }
    }
}], 
//mongodb查找重复数据过大时需要添加 allowDiskUse属性
//聚合的结果必须要限制在16M以内操作,(mongodb支持的最大影响信息的大小),否则必须放在磁盘中做缓存(allowDiskUse=True)
{
    allowDiskUse: true
}
//以上条件的查询结果转换成了doc 对象,在下面的函数调用是则需要使用doc 这个对象代替查询结果
//以下语法相当于  delete from 表名 where _id in (doc.uniqueIds) and value != doc.value
).forEach(function(doc){
    db.getCollection('ts_data_i').remove({
        _id: {
            $in: doc.uniqueIds
        },
        value:{$ne:doc.value}
    });
})

补充一下~:
以上语句执行后可能会残留数值相同的重复数据,如下

/* 1 */
{
    "_id" : ObjectId("5e4f5c47873c4c8"),
    "deviceId" : "SHKT_1",
    "tagCode" : "S0010",
    "time" : "2020-02-19 00:00:00",
    "type" : 7,
    "value" : 0.0
}

/* 2 */
{
    "_id" : ObjectId("5e4f5c47873c4c7"),
    "deviceId" : "SHKT_1",
    "tagCode" : "S0010",
    "time" : "2020-02-19 00:00:00",
    "type" : 7,
    "value" : 0.0
}

那就需要跑一下参考链接中的脚本了,按照我自己的业务需求则是以下脚本:

db.getCollection('ts_data_i').aggregate(
[
//这个$match 代表的是查询条件  即为where
{$match :{
        time:/^2020-02-19/
        ,deviceId:"SHKT_1"
        ,tagCode:/^S000/
        
    }
},

{$group : 
    {   _id : {
        'time': '$time',
        'tagCode': '$tagCode',
        'deviceId': '$deviceId'
        },
        
        'count': {
                '$sum': 1
            },
        'uniqueIds': {
          '$addToSet': '$_id'
        }
    }
},
//这个$match代表的是分组后的数据的筛选条件  相当于mysql中的having 
{
        '$match': {
            'count': {
                '$gt': 1
            }
        }
    }
], {
    allowDiskUse: true
}

).forEach(function(doc){
	//doc.uniqueIds.shift();表示从数组第一个值开始删除;作用是踢除重复数据其中一个_id,让后面的删除语句不会删除所有数据
    doc.uniqueIds.shift();
    db.getCollection('ts_data_i').remove({
        _id: {
            $in: doc.uniqueIds
        }
    });
})
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值