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

如何用Spring Data Mongo API实现带条件的findAndModify操作?

正确实现MongoDB findAndModify的Spring Data Mongo Kotlin代码

需求回顾

需要实现与以下MongoDB原生findAndModify等价的Spring Data Mongo逻辑:

db.account_balances.findAndModify({
  query: { _id: '1234' },
  update: [
    {
      $set: {
        'fieldToUpdate': {
          $cond: {
            if: { 
              $and: [ 
                { $lte: ['$updatedAt', new ISODate('2024-09-24T00:00:00.000Z')] },
                { $lt: [ { $toLong: '$numericalStringField' }, 1000 ] }
              ],
            },
            then: 15000.0,
            else: '$fieldToUpdate'
          }
        }
      }
    }
  ],
  new: true
})

核心逻辑:根据_id查找文档,仅当文档满足updatedAt ≤ 指定日期且numericalStringField转Long后 < 1000时,将fieldToUpdate设为15000.0,否则保持原字段值,最后返回更新后的文档。

问题分析

之前的代码错误在于将Criteria对象直接传入ConditionalOperators.when,而ConditionalOperators需要使用**聚合表达式(Aggregation Expression)**来构建$cond的判断条件,而非查询用的Criteria。

正确实现代码

import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.findAndModify
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.Update
import org.springframework.data.mongodb.core.query.UpdateDefinition
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators
import org.springframework.data.mongodb.core.aggregation.ComparisonOperators
import org.springframework.data.mongodb.core.aggregation.ConvertOperators
import org.springframework.data.mongodb.core.query.FindAndModifyOptions

// 自定义常量与参数示例
const val COLLECTION_NAME = "account_balances"
val targetId = "1234"
val eventDate = org.bson.types.DateTime("2024-09-24T00:00:00.000Z")
val targetValue = 15000.0
const val FIELD_TO_UPDATE = "fieldToUpdate"
const val UPDATED_AT = "updatedAt"
const val NUMERICAL_STRING_FIELD = "numericalStringField"

fun updateAccountBalance(mongoTemplate: MongoTemplate) {
    // 构建$cond的判断条件:两个聚合表达式的逻辑与
    val updateCondition = ConditionalOperators.and(
        // 条件1:updatedAt ≤ 指定日期
        ComparisonOperators.Lte.valueOf(UPDATED_AT).lessThanEqualToValue(eventDate),
        // 条件2:numericalStringField转Long后 < 1000
        ComparisonOperators.Lt.valueOf(
            ConvertOperators.ToLong.toLong(NUMERICAL_STRING_FIELD)
        ).lessThanValue(1000L)
    )

    // 构建$set操作:满足条件则设为targetValue,否则保留原字段值
    val update: UpdateDefinition = Update.update(
        FIELD_TO_UPDATE,
        ConditionalOperators.`when`(updateCondition)
            .then(targetValue)
            .otherwiseValueOf(FIELD_TO_UPDATE)
    )

    // 执行findAndModify
    val result = mongoTemplate.findAndModify(
        Query.query(Criteria.where("_id").`is`(targetId)),
        update,
        FindAndModifyOptions.options().returnNew(true), // 返回更新后的文档
        COLLECTION_NAME
    )

    // 结果处理示例
    result?.let {
        println("更新后的文档:$it")
    } ?: println("未找到匹配_id的文档")
}

关键说明

  1. 聚合表达式构建条件:用ConditionalOperators.and组合两个聚合表达式,完全对应MongoDB原生的$and逻辑
  2. 类型转换与比较:通过ConvertOperators.ToLong.toLong将字符串字段转为Long类型,再用ComparisonOperators.Lt完成小于比较
  3. Update构建:直接使用Update.update传入$cond表达式,替代之前错误的SetOperation用法
  4. 选项配置:FindAndModifyOptions设置returnNew(true)对应原生查询的new: true,原生查询未开启upsert,此处也无需配置

内容的提问来源于stack exchange,提问作者Ichroman Raditya Duwila

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:05:17