gomog/manual/UPDATE_OPERATORS.md

9.5 KiB
Raw Blame History

Gomog 更新操作符参考文档

版本: v1.0.0-alpha
最后更新: 2026-03-14


📖 目录

  1. 字段更新操作符
  2. 数组更新操作符
  3. 算术更新操作符
  4. 位运算更新操作符
  5. 条件更新操作符
  6. 使用示例

字段更新操作符

$set - 设置字段

设置字段的值。如果字段不存在,则创建该字段。

语法:

{"$set": {"<field>": <value>}}

示例:

// 设置单个字段
{"$set": {"status": "active"}}

// 设置多个字段
{
  "$set": {
    "status": "active",
    "lastModified": ISODate("2024-01-01")
  }
}

// 设置嵌套字段
{"$set": {"address.city": "Beijing"}}

$unset - 移除字段

移除一个或多个字段。

语法:

{"$unset": {"<field>": ""}}
// 或
{"$unset": {"<field1>": "", "<field2>": ""}}

示例:

// 移除单个字段
{"$unset": {"tempField": ""}}

// 移除多个字段
{
  "$unset": {
    "oldField": "",
    "deprecated": ""
  }
}

$setOnInsert - 仅在插入时设置

仅在 upsert 操作创建新文档时设置字段。

语法:

{"$setOnInsert": {"<field>": <value>}}

示例:

{
  "$setOnInsert": {
    "createdAt": ISODate("2024-01-01"),
    "createdBy": "system"
  }
}

$rename - 重命名字段

重命名字段名。

语法:

{"$rename": {"<oldField>": "<newField>"}}

示例:

// 重命名单个字段
{"$rename": {"oldName": "newName"}}

// 重命名多个字段
{
  "$rename": {
    "firstName": "givenName",
    "lastName": "familyName"
  }
}

$currentDate - 设置为当前时间

将字段设置为当前日期或时间戳。

语法:

{"$currentDate": {"<field>": <type>}}

类型:

  • true: BSON Date (默认)
  • {$type: "timestamp"}: BSON Timestamp

示例:

// 设置为 Date
{"$currentDate": {"lastModified": true}}

// 设置为 Timestamp
{"$currentDate": {"lastModified": {$type: "timestamp"}}}

数组更新操作符

$push - 推入元素

向数组中添加一个元素。

语法:

{"$push": {"<arrayField>": <value>}}

示例:

// 添加单个元素
{"$push": {"tags": "mongodb"}}

// 添加对象到数组
{"$push": {"scores": {"value": 95, "date": ISODate("2024-01-01")}}}

// 配合 $each 使用
{
  "$push": {
    "tags": {
      "$each": ["database", "nosql"],
      "$sort": 1,
      "$slice": 10
    }
  }
}

修饰符:

  • $each: 添加多个值
  • $sort: 排序数组
  • $slice: 限制数组大小
  • $position: 指定插入位置

$addToSet - 添加到集合

向数组中添加元素(如果不存在)。

语法:

{"$addToSet": {"<arrayField>": <value>}}

示例:

// 添加唯一值
{"$addToSet": {"tags": "database"}}

// 配合 $each 使用
{
  "$addToSet": {
    "tags": {
      "$each": ["mongodb", "nosql", "database"]
    }
  }
}

$pop - 弹出元素

从数组中移除第一个或最后一个元素。

语法:

{"$pop": {"<arrayField>": <direction>}}

方向:

  • 1: 移除最后一个元素
  • -1: 移除第一个元素

示例:

// 移除最后一个元素
{"$pop": {"items": 1}}

// 移除第一个元素
{"$pop": {"items": -1}}

$pull - 拉出元素

从数组中移除所有匹配的元素。

语法:

{"$pull": {"<arrayField>": {<query>}}}

示例:

// 移除等于特定值的元素
{"$pull": {"tags": "deprecated"}}

// 移除满足条件的元素
{"$pull": {
  "items": {
    "price": {"$lt": 100}
  }
}}

// 移除数组中的对象
{"$pull": {
  "users": {
    "status": "inactive"
  }
}}

$pullAll - 拉出多个元素

从数组中移除多个指定的元素。

语法:

{"$pullAll": {"<arrayField>": [<value1>, <value2>, ...]}}

示例:

{"$pullAll": {"tags": ["deprecated", "obsolete", "old"]}}

$splice - 拼接数组

修改数组内容(类似 JavaScript 的 splice

语法:

{"$splice": {"<arrayField>": [[start, deleteCount, ...items]]}}

示例:

// 从索引 2 开始删除 1 个元素,插入 2 个新元素
{"$splice": {"items": [[2, 1, "new1", "new2"]]}}

算术更新操作符

$inc - 递增

将字段的值增加指定的数量。

语法:

{"$inc": {"<field>": <number>}}

示例:

// 增加计数
{"$inc": {"viewCount": 1}}

// 减少数值
{"$inc": {"stock": -5}}

// 增加浮点数
{"$inc": {"balance": 100.50}}

$mul - 乘法

将字段的值乘以指定的数量。

语法:

{"$mul": {"<field>": <number>}}

示例:

// 打 9 折
{"$mul": {"price": 0.9}}

// 增加 10%
{"$mul": {"quantity": 1.1}}

$min - 最小值

只有当指定值小于当前值时才更新字段。

语法:

{"$min": {"<field>": <value>}}

示例:

// 更新最低价格
{"$min": {"lowPrice": 50}}

$max - 最大值

只有当指定值大于当前值时才更新字段。

语法:

{"$max": {"<field>": <value>}}

示例:

// 更新最高分数
{"$max": {"highScore": 95}}

位运算更新操作符

$bit - 位运算

对整数字段执行位运算。

语法:

{"$bit": {"<field>": {<operation>: <value>}}}

支持的运算:

  • and: 按位与
  • or: 按位或
  • xor: 按位异或

示例:

// 按位与
{"$bit": {"flags": {"and": 15}}}  // 保留低 4 位

// 按位或
{"$bit": {"permissions": {"or": 8}}}  // 设置第 4 位

// 按位异或
{"$bit": {"status": {"xor": 1}}}  // 切换第 1 位

条件更新操作符

$ - 数组过滤器

更新数组中匹配的第一个元素。

语法:

{"<arrayField>.<index>": <value>}

示例:

// 更新数组第一个元素
{"$set": {"scores.0": 100}}

// 使用 $[identifier] 更新匹配的元素
{
  "$set": {
    "students.$[elem].grade": "A"
  }
},
{
  "arrayFilters": [
    {"elem.name": "Alice"}
  ]
}

$[] - 更新所有数组元素

更新数组中的所有元素。

语法:

{"<arrayField>.$[]": <value>}

示例:

// 更新所有数组元素
{"$set": {"scores.$[]": 0}}

$[] - 带过滤的数组更新

更新数组中匹配条件的元素。

语法:

{"<arrayField>.$[<identifier>]": <value>}

示例:

{
  "$set": {
    "students.$[s].grade": "A"
  }
},
{
  "arrayFilters": [
    {"s.score": {"$gte": 90}}
  ]
}

使用示例

用户资料更新

{
  "$set": {
    "name": "张三",
    "email": "zhangsan@example.com"
  },
  "$inc": {
    "loginCount": 1
  },
  "$currentDate": {
    "lastLogin": true
  }
}

购物车操作

{
  "$push": {
    "items": {
      "productId": "prod_001",
      "quantity": 2,
      "price": 99.99
    }
  },
  "$inc": {
    "totalAmount": 199.98
  },
  "$set": {
    "updatedAt": ISODate("2024-01-01")
  }
}

库存管理

{
  "$inc": {
    "stock": -5,
    "soldCount": 5
  },
  "$min": {
    "lowStockAlert": 10
  },
  "$set": {
    "lastSale": ISODate("2024-01-01")
  }
}

评分系统

{
  "$push": {
    "ratings": {
      "userId": "user_001",
      "score": 5,
      "comment": "Excellent!"
    }
  },
  "$inc": {
    "ratingCount": 1,
    "totalScore": 5
  },
  "$set": {
    "averageRating": {"$divide": ["$totalScore", "$ratingCount"]}
  }
}

标签管理

{
  "$addToSet": {
    "tags": "new"
  },
  "$pull": {
    "tags": "old"
  },
  "$push": {
    "history": {
      "$each": ["tag_updated"],
      "$slice": -10
    }
  }
}

批量更新

// 更新多个文档
{
  "filter": {"department": "技术部"},
  "update": {
    "$inc": {"salary": 1000},
    "$set": {"adjusted": true}
  },
  "multi": true
}

Upsert 操作

{
  "filter": {"email": "user@example.com"},
  "update": {
    "$setOnInsert": {
      "email": "user@example.com",
      "createdAt": ISODate("2024-01-01")
    },
    "$set": {
      "lastSeen": ISODate("2024-01-01")
    },
    "$inc": {
      "visitCount": 1
    }
  },
  "upsert": true
}

复杂数组操作

{
  "$push": {
    "scores": {
      "$each": [95, 87, 92],
      "$sort": -1,
      "$slice": 5,
      "$position": 0
    }
  }
}

嵌套字段更新

{
  "$set": {
    "address.street": "长安街",
    "address.city": "北京",
    "contact.phone": "123456789"
  },
  "$unset": {
    "address.oldAddress": ""
  }
}

最佳实践

1. 原子性保证

Gomog 的更新操作是原子的,可以安全地并发使用。

// 安全的计数器递增
{"$inc": {"viewCount": 1}}

2. 使用 $setOnInsert 避免覆盖

// ✅ 推荐:只在插入时设置创建时间
{
  "$setOnInsert": {"createdAt": ISODate()},
  "$set": {"updatedAt": ISODate()}
}

3. 合理使用数组修饰符

// 限制数组大小,防止无限增长
{
  "$push": {
    "history": {
      "$each": [newItem],
      "$slice": -100  // 只保留最后 100 条
    }
  }
}

4. 使用 arrayFilters 精确更新

// 精确定位要更新的数组元素
{
  "$set": {"grades.$[g].grade": "A"},
  "arrayFilters": [{"g.subject": "math"}]
}

5. 避免频繁更新大文档

// ❌ 不推荐:每次更新整个文档
{"$set": {entireDocument}}

// ✅ 推荐:只更新变化的字段
{"$set": {"changedField": newValue}}

维护者: Gomog Team
许可证: MIT