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

Mongoid中first_or_create与first_or_create!两个方法有什么区别

Mongoid 中 first_or_create 与 first_or_create! 的区别与使用规则

两个方法的基础逻辑一致:优先按传入的查询条件匹配集合内第一条符合要求的文档,若没有匹配结果则尝试用查询条件+传入的补充属性新建文档,核心差异集中在「新建文档校验失败」时的处理逻辑:

  • first_or_create 行为规则
    当新建文档触发模型校验(validations)未通过时,不会抛出异常,会直接返回未持久化到数据库的无效文档对象,你可以通过返回对象的errors属性获取具体校验失败原因。
    示例代码:

    class User
      include Mongoid::Document
      field :email, type: String
      field :age, type: Integer
      validates :email, presence: true
    end
    
    # 缺失必填属性email,新建校验失败
    user = User.where(age: 20).first_or_create
    user.persisted? # 返回 false,说明没有存入数据库
    user.errors.full_messages # 返回 ["Email can't be blank"]
    

    适用场景:需要在业务流程里手动处理创建失败分支,不希望通过异常捕获做流程控制的场景,比如表单提交后把校验错误回显给用户的业务逻辑。

  • first_or_create! 行为规则
    当新建文档触发模型校验未通过时,会直接抛出Mongoid::Errors::Validations异常,不会静默返回未保存的对象。
    示例代码:

    # 同样缺失必填属性email,以下代码会直接抛出异常
    begin
      User.where(age: 20).first_or_create!
    rescue Mongoid::Errors::Validations => e
      # 可在异常分支中做错误日志记录、告警等处理
      puts e.document.errors.full_messages
    end
    

    适用场景:你确认传入参数完全符合校验规则,创建失败属于预期外的程序错误,需要异常直接抛出触发监控告警,或者配合事务做回滚逻辑的场景。

注意:两个方法在匹配到已有文档时,都不会用传入的额外属性更新已有文档内容,不要和upsert类更新/插入方法的逻辑混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 00:54:44