Mongo 实践之分组去重 aggregate group

2024-04-30 19:43:39 浏览数 (4)

现在工作中的数据库存储都由 MySQL 切换到了MongoDB ,我计划写一个合集来记录用到的一些 Mongo 语句,有些是Mongo sql 语法,有些是 pymongo 的写法。

前段时间是需要查询一张表并对里面的数据去重。collection 表名叫 datatagging,它主要包含 3 个字段 "_id"、"unique_path"、"modified" ,我希望对 unique_path 这个字段去重,并根据 modified 这个日期字段保留最新的一条,返回的结果里必须包含 id。

实现的思路和希望的诉求是一样的,对 unique_path 进行分组,并且按照modified 倒序排列取每组第一条记录,然后把分组结果再输出

Mongo sql 是这样写的

代码语言:javascript复制
from pymongo import MongoClient

# 连接到 MongoDB
client = MongoClient('mongodb://localhost:27017/')
db = client.your_database_name  # 更改为你的数据库名称
collection = db.datatagging

# 构建聚合管道
pipeline = [
    {
        "$sort": {"unique_path": 1, "modified": -1}  # 按照 unique_path 升序,modified 降序排序
    },
    {
        "$group": {
            "_id": "$unique_path",
            "latestModified": {"$first": "$modified"},  # 获取每个 unique_path 分组中 modified 最新的值
            "document": {"$first": "$$ROOT"}  # 获取整个文档对象
        }
    },
    {
        "$replaceRoot": {"newRoot": "$document"}  # 将保存的整个文档对象作为输出文档
    },
    {
        "$sort": {"modified": -1}  # 按照 modified 字段倒序排列
    }
]

# 执行聚合查询
result = list(collection.aggregate(pipeline))

# 输出结果
ids = []
for doc in result:
    print(doc["_id"])

aggregate 接收一个数组参数,里面包含多个对象,可以把这些对象看作一个管道,从第一个对象串行执行到最后一个对象。group 阶段用于对文档进行分组聚合操作。group 阶段的 _id 字段指定了用于分组的键,因为对 unique_path 分组,所以我 _id 设置了unique_path

通过上面查询出来的结果得到了去重后的文档ids,后面再对整张表查询将不在 ids 中的记录删除掉

代码语言:javascript复制
delete_result = collection.delete_many({"_id": {"$nin": ids}})

# 输出删除的记录数
print("Deleted", delete_result.deleted_count, "documents.")

可以通过 delete_result.deleted_count 获取删除的条数

1 人点赞