You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB中更新符合特定规则的重复文档?

Solution for Identifying and Updating Duplicate Documents

Got it, let's tackle this problem step by step. You need to flag older duplicate documents (matching ipAddr and bccId, with active: true but different sessionId) by setting their active field to false. Here's how to do it properly with MongoDB's aggregation and update operations:

Step 1: Identify Duplicate Documents to Update

First, use an aggregation pipeline to pinpoint which documents need their active field flipped. This pipeline will:

  • Filter for documents where active is already true
  • Group them by ipAddr and bccId to find duplicates
  • Sort each group by lastUpdated (newest first)
  • Exclude the newest document in each group (since we want to keep it active)
db.mycollection.aggregate([
  // Filter only active documents
  { $match: { active: true } },
  // Group by ipAddr + bccId, collect all docs in each group
  {
    $group: {
      _id: { ipAddr: "$ipAddr", bccId: "$bccId" },
      docs: { $push: { _id: "$_id", sessionId: "$sessionId", lastUpdated: "$lastUpdated" } },
      totalDocs: { $sum: 1 }
    }
  },
  // Keep only groups with duplicates (more than 1 document)
  { $match: { totalDocs: { $gt: 1 } } },
  // Sort each group's docs by lastUpdated (newest first)
  {
    $addFields: {
      sortedDocs: { $sortArray: { input: "$docs", sortBy: { lastUpdated: -1, _id: -1 } } }
    }
  },
  // Skip the newest document, keep the rest to update
  {
    $addFields: {
      docsToDeactivate: { $slice: ["$sortedDocs", 1, { $size: "$sortedDocs" }] }
    }
  },
  // Unwind the list of docs to update into individual documents
  { $unwind: "$docsToDeactivate" },
  // Keep only the _id of documents to update
  { $replaceRoot: { newRoot: { _id: "$docsToDeactivate._id" } } }
])

Note: The _id: -1 in the sort step handles edge cases where two documents have the exact same lastUpdated value—it ensures we only keep one document active (the one with the larger _id).

Step 2: Batch Update the Identified Documents

Once you have the list of documents to deactivate, you can use updateMany to set their active field to false. Here's how to combine the aggregation and update in one workflow:

Option 1: Two-Step Approach (Works in All MongoDB Versions)

// First, fetch all _ids of documents to deactivate
const idsToDeactivate = db.mycollection.aggregate([
  // Paste the aggregation pipeline from Step 1 here
]).map(doc => doc._id);

// Batch update the documents
db.mycollection.updateMany(
  { _id: { $in: idsToDeactivate } },
  { $set: { active: false } }
);

Option 2: Single-Step with $merge (MongoDB 4.2+)

For a more efficient, single-step operation, use MongoDB's $merge stage to write the update directly from the aggregation:

db.mycollection.aggregate([
  // Paste the aggregation pipeline from Step 1 here (up to $replaceRoot)
  {
    $merge: {
      into: "mycollection",
      on: "_id",
      whenMatched: { $set: { active: false } },
      whenNotMatched: "discard" // Ignore any unexpected matches
    }
  }
]);

Verification

After running the update, you can verify the result with this query to ensure only the newest document per ipAddr/bccId pair remains active:

db.mycollection.aggregate([
  { $match: { active: true } },
  {
    $group: {
      _id: { ipAddr: "$ipAddr", bccId: "$bccId" },
      count: { $sum: 1 }
    }
  },
  { $match: { count: { $gt: 1 } } }
])

If this returns no results, your operation worked correctly!

内容的提问来源于stack exchange,提问作者Igor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:39:49