【问题标题】:Cannot overwrite model once compiled Mongoose编译 Mongoose 后无法覆盖模型
【发布时间】:2013-10-03 18:25:17
【问题描述】:

不确定我做错了什么,这是我的 check.js

var db = mongoose.createConnection('localhost', 'event-db');
db.on('error', console.error.bind(console, 'connection error:'));

var a1= db.once('open',function(){
var user = mongoose.model('users',{ 
       name:String,
       email:String,
       password:String,
       phone:Number,
      _enabled:Boolean
     });

user.find({},{},function (err, users) {
    mongoose.connection.close();
    console.log("Username supplied"+username);
    //doSomethingHere })
    });

这是我的 insert.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/event-db')

var user = mongoose.model('users',{
     name:String,
     email:String,
     password: String,
     phone:Number,
     _enabled:Boolean
   });

var new_user = new user({
     name:req.body.name,
     email: req.body.email,
     password: req.body.password,
     phone: req.body.phone,
     _enabled:false
   });

new_user.save(function(err){
    if(err) console.log(err); 
   });

每当我尝试运行 check.js 时,我都会收到此错误

编译后无法覆盖“用户”模型

我知道这个错误是由于 Schema 不匹配造成的,但我看不到这是在哪里发生的?我对 mongoose 和 nodeJS 还很陌生。

这是我从 MongoDB 的客户端界面得到的信息:

MongoDB shell version: 2.4.6 connecting to: test 
> use event-db 
  switched to db event-db 
> db.users.find() 
  { "_id" : ObjectId("52457d8718f83293205aaa95"), 
    "name" : "MyName", 
    "email" : "myemail@me.com", 
    "password" : "myPassword", 
    "phone" : 900001123, 
    "_enable" : true 
  } 
>

【问题讨论】:

  • 这是我从 MongoDB 的客户端界面得到的信息:MongoDB shell 版本:2.4.6 连接到:test > 使用 event-db 切换到 db event-db > db.users。查找(){“_id”:ObjectId(“52457d8718f83293205aaa95”),“名称”:“MyName”,“电子邮件”:“myemail@me.com”,“密码”:“myPassword”,“电话”:900001123,“ _enable" : true } >
  • 有时这只是我们犯的一个愚蠢的错误,在我的情况下:导出就像 {userModel:model("user",userSchema)...所以每次他访问文件时它都会重新创建模型和触发错误...所以不要像这样导出,而是创建一个常量“const userModel=model("user",userSchema) 然后像 module.exports = { userModel } 一样导出它

标签: node.js mongodb model express mongoose


【解决方案1】:

发生错误是因为您已经定义了架构,然后您又重新定义了架构。通常你应该做的是将模式实例化一次,然后让一个全局对象在需要时调用它。

例如:

user_model.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var userSchema = new Schema({
   name:String,
   email:String,
   password:String,
   phone:Number,
   _enabled:Boolean
});
module.exports = mongoose.model('users', userSchema);          

check.js

var mongoose = require('mongoose');
var User = require('./user_model.js');

var db = mongoose.createConnection('localhost', 'event-db');
db.on('error', console.error.bind(console, 'connection error:'));
var a1= db.once('open',function(){
  User.find({},{},function (err, users) {
    mongoose.connection.close();
    console.log("Username supplied"+username);
    //doSomethingHere 
  })
});

插入.js

var mongoose = require('mongoose');
var User = require('./user_model.js');

mongoose.connect('mongodb://localhost/event-db');
var new_user = new User({
    name:req.body.name
  , email: req.body.email
  , password: req.body.password
  , phone: req.body.phone
  , _enabled:false 
});
new_user.save(function(err){
  if(err) console.log(err); 
});

【讨论】:

  • 避免导出/需要模型——如果有任何模型有refs 到其他模型,这可能会导致依赖噩梦。使用var User = mongoose.model('user') 而不是require
  • 在定义用于测试架构迁移代码之后更改架构实际上很有用。
  • @wprl 你能进一步解释一下吗?为什么要求它会产生问题?
  • 这个答案具有误导性。事实是,如果只有一个 mongoDB 服务器实例和多个数据库,如果您在另一个应用程序中定义已经使用的数据库,那么您会收到这样的错误。就这么简单
【解决方案2】:

如果你在这里做了,你可能遇到了和我一样的问题。 我的问题是我正在定义另一个具有相同名称的模型。 我将我的画廊和文件模型称为“文件”。该死的复制和粘贴!

【讨论】:

    【解决方案3】:

    您可能会收到此错误的另一个原因是,如果您在不同的文件中使用相同的模型,但您的 require 路径的大小写不同。

    例如,在我的情况下,我在一个文件中有require('./models/User'),然后在另一个需要访问用户模型的文件中,我有require('./models/user')

    我猜模块和猫鼬的查找将其视为不同的文件。一旦我确定这两种情况都匹配,它就不再是问题了。

    【讨论】:

    • 这确实是一个非常棘手的问题 - 我认为它是特定于操作系统的(它应该只发生在 Mac 和 Windows 上,因为 FS 忽略了这种情况)。我遇到了这个问题,但幸运地看到了你的回答 :) 非常感谢 Jonnie!
    • 这个问题发生在我的 OS X 系统中。
    • 这对我来说是一样的。所有欢呼 OS X 及其(默认情况下不区分大小写)文件系统
    • 感谢您的帮助。这正是我在 MacOS 上遇到的问题。
    【解决方案4】:

    如果您使用的是 expressjs,您可能需要将模型定义移到 app.get() 之外,这样它只会在脚本实例化时调用一次。

    【讨论】:

    • 这没有意义,猫鼬模型只定义一次,除非命名有问题(例如案例),一旦第一次调用它就会被初始化,未来的需求应该只是获取实例和不重新实例化它
    • 这不是解决方案。
    【解决方案5】:

    我在单元测试时遇到了这个问题。

    第一次调用模型创建函数时,猫鼬将模型存储在您提供的键下(例如“用户”)。如果你多次使用同一个 key 调用模型创建函数,mongoose 不会让你覆盖现有的模型。

    你可以检查模型是否已经存在于猫鼬中:

    let users = mongoose.model('users')
    

    如果模型不存在,这将引发错误,因此您可以将其包装在 try/catch 中,以便获取或创建模型:

    let users
    try {
      users = mongoose.model('users')
    } catch (error) {
      users = mongoose.model('users', <UsersSchema...>)
    }
    

    【讨论】:

    • +1 我遇到了同样的问题,我需要为插件设置一些配置,然后才能定义我的架构。这与 mocha 完全不搭,最后我放弃了,只是采用了这种 try catch 方法
    • 我使用的是相同的,但反过来,这很邪恶:try exports.getModel = ()-&gt; mongoose.model('User', userSchema) catch err exports.getModel = ()-&gt; mongoose.model('User')
    • 谢谢你的好先生,在这个问题上浪费了 5 个多小时。与我习惯的节点服务器不同,我使用的是无服务器。
    • 2021 年更新:export default mongoose.models["user"] ?? mongoose.model("user", schema)
    【解决方案6】:

    对于一个集合,模式定义应该是唯一的,对于一个集合来说,它不应该超过一个模式。

    【讨论】:

      【解决方案7】:

      我知道有一个公认的解决方案,但我认为当前的解决方案会产生大量样板文件,以便您可以测试模型。我的解决方案本质上是将您的模型放在一个函数中,如果模型尚未注册,则返回新模型,但如果已注册,则返回现有模型。

      function getDemo () {
        // Create your Schema
        const DemoSchema = new mongoose.Schema({
          name: String,
          email: String
        }, {
          collection: 'demo'
        })
        // Check to see if the model has been registered with mongoose
        // if it exists return that model
        if (mongoose.models && mongoose.models.Demo) return mongoose.models.Demo
        // if no current model exists register and return new model
        return mongoose.model('Demo', DemoSchema)
      }
      
      export const Demo = getDemo()
      

      到处打开和关闭连接令人沮丧,而且压缩效果不好。

      这样,如果我在两个不同的地方或更具体地在我的测试中需要模型,我就不会出错,并且会返回所有正确的信息。

      【讨论】:

        【解决方案8】:

        我在“观看”测试时遇到了这个问题。 编辑测试后,手表重新运行了测试,但由于这个原因它们失败了。

        我通过检查模型是否存在然后使用它来修复它,否则创建它。

        import mongoose from 'mongoose';
        import user from './schemas/user';
        
        export const User = mongoose.models.User || mongoose.model('User', user);
        

        【讨论】:

        • 这对我有用。我已将module.export = User 更改为export defaults User。我也有 refs 来自其他模型的用户。我不确定为什么从module.exports 更改为export default 会带来这个问题。不过,这个答案似乎已经解决了。
        • 糟糕mongoose.models 不存在,至少在最近的版本中
        • 我遇到了同样的问题,但通过在所有测试之前清除所有模型来修复它:for (let model in mongoose.models) delete mongoose.models[model]
        • 在最新版本的 Mongoose 中使用它,它似乎工作得很好!
        • 这对我有用。
        【解决方案9】:

        当我这样写时发生在我身上:

        import User from '../myuser/User.js';
        

        然而,真正的路径是'../myUser/User.js'

        【讨论】:

        • 在导入时混合模式路径的大小写似乎会导致此问题 - 检查导入模式的所有文件是否使用相同的大小写。
        【解决方案10】:

        我一直遇到这个问题,这不是因为架构定义,而是因为无服务器离线模式 - 我只是设法通过以下方式解决它:

        serverless offline --skipCacheInvalidation
        

        这里提到了https://github.com/dherault/serverless-offline/issues/258

        希望这可以帮助其他在无服务器上构建项目并运行离线模式的人。

        【讨论】:

        • 我发现跳过缓存失效,不断重新加载很烦人,而是这样做module.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
        • 这对我来说非常有用并且效果很好,直到我再次在另一个模型中导入一个模型。为了防止这个错误,我们需要使用@asked_io 的解决方案。
        • 尝试了@Moosecunture 解决方案,但出现错误。但它奏效了。谢谢。
        【解决方案11】:

        如果您使用相同的集合名称定义 2 个不同的架构,则可能会出现此问题

        【讨论】:

          【解决方案12】:

          是因为您的架构已经存在,请在创建新架构之前进行验证。

          var mongoose = require('mongoose');
          module.exports = function () {
          var db = require("../libs/db-connection")();
          //schema de mongoose
          var Schema = require("mongoose").Schema;
          
          var Task = Schema({
              field1: String,
              field2: String,
              field3: Number,
              field4: Boolean,
              field5: Date
          })
          
          if(mongoose.models && mongoose.models.tasks) return mongoose.models.tasks;
          
          return mongoose.model('tasks', Task);
          

          【讨论】:

            【解决方案13】:
            If you want to overwrite the existing class for different collection using typescript
            then you have to inherit the existing class from different class.
            
            export class User extends Typegoose{
              @prop
              username?:string
              password?:string
            }
            
            
            export class newUser extends User{
                constructor() {
                    super();
                }
            }
            
            export const UserModel = new User ().getModelForClass(User , { schemaOptions: { collection: "collection1" } });
            
            export const newUserModel = new newUser ().getModelForClass(newUser , { schemaOptions: { collection: "collection2" } });
            

            【讨论】:

              【解决方案14】:

              如果你是离线使用Serverless,又不想使用--skipCacheInvalidation,可以很好的使用:

              module.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
              

              【讨论】:

              • 如果您将一个模型导入到另一个模型中,您也必须使用它,即使使用--skipCacheInvalidation
              • 这是我正在寻找的确切答案,用于 Next.js。我希望这在页面上更高!
              • 但问题是 Typescript 不会检测到接口中定义的模型。用户,它将回退到任何
              • 我从来没有遇到过这个问题,直到我在 Next.js 中尝试了 mongoose 这个解决方案对我有用,谢谢!我认为 Next.js 正在发生这种情况,因为它们的开发模式是如何配置的。也许 Next.js 团队可以改进这一点......
              • @rony 我在使用 TypeScript 时遇到了这个问题,并通过以下方式解决了它: const getModel = () => model("User", UserSchema); module.exports = (models.User || getModel()) as ReturnType;
              【解决方案15】:

              你可以很容易地解决这个问题

              delete mongoose.connection.models['users'];
              const usersSchema = mongoose.Schema({...});
              export default mongoose.model('users', usersSchema);
              

              【讨论】:

                【解决方案16】:

                我有一种情况,我必须为每个请求动态创建模型,因此我收到了这个错误,但是,我用来修复它的是使用deleteModel 方法,如下所示:

                var contentType = 'Product'
                
                var contentSchema = new mongoose.Schema(schema, virtuals);
                
                var model = mongoose.model(contentType, contentSchema);
                
                mongoose.deleteModel(contentType);
                

                我希望这可以帮助任何人。

                【讨论】:

                  【解决方案17】:

                  我通过添加解决了这个问题

                  mongoose.models = {}
                  

                  行前:

                  mongoose.model(<MODEL_NAME>, <MODEL_SCHEMA>)
                  

                  希望它能解决你的问题

                  【讨论】:

                  • 这就是我所做的,它修复了它。 mongoose.connection.models = {};
                  • Typescript 抛出错误cannot assign to models because it is read only property
                  【解决方案18】:
                  The reason of this issue is: 
                  
                  you given the model name "users" in the line 
                  <<<var user = mongoose.model('users' {>>> in check.js file
                  
                  and again the same model name you are giving in the insert file
                  <<< var user = mongoose.model('users',{ >>> in insert.js
                  
                  This "users" name shouldn't be same when you declare a model that should be different 
                  in a same project.
                  

                  【讨论】:

                    【解决方案19】:

                    在创建之前解决此检查模型是否存在:

                    if (!mongoose.models[entityDBName]) {
                      return mongoose.model(entityDBName, entitySchema);
                    }
                    else {
                      return mongoose.models[entityDBName];
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      对于所有因为代码库混合了 TypegooseMongoose 的人:

                      为每一个创建一个数据库连接:

                      猫鼬:

                      module.exports = db_mongoose.model("Car", CarSchema);
                      

                      Typegoose:

                      db_typegoose.model("Car", CarModel.schema, "cars");
                      

                      【讨论】:

                        【解决方案21】:

                        我遇到了同样的问题, 原因是我在 JS 函数中定义了模式和模型,它们应该在节点模块中全局定义,而不是在函数中。

                        【讨论】:

                          【解决方案22】:

                          还有另一种抛出此错误的方法。

                          请记住,模型的路径区分大小写。

                          在这个涉及“类别”模型的类似示例中,在以下情况下会引发错误:

                          1) 在两个文件中提到了 require 语句:..category.js 和 ..index.js 2)我第一个,大小写是正确的,在第二个文件中它不是这样的:

                          category.js

                          index.js

                          【讨论】:

                            【解决方案23】:

                            您在 check.js 和 insert.js 中使用具有相同变量名称“user”的 mongoose.model。

                            【讨论】:

                              【解决方案24】:

                              我只是有一个错误的复制粘贴。在一行中,我的名称与其他模型(广告模型)中的名称相同:

                              const Admin = mongoose.model('Ad', adminSchema);
                              

                              正确的是:

                              const Admin = mongoose.model('Admin', adminSchema);
                              

                              顺便说一句,如果有人有“自动保存”,并使用索引进行如下查询:

                              **adSchema**.index({title:"text", description:"text", phone:"text", reference:"text"})
                              

                              它必须删除索引,并为正确的模型重写:

                              **adminSchema**.index({title:"text", description:"text", phone:"text", reference:"text"})
                              

                              【讨论】:

                                【解决方案25】:

                                由于再次调用模型而发生此问题。通过将模型代码包装在 try catch 块中来解决此问题。打字稿代码是这样的 -

                                         Import {Schema, model} from 'mongoose';
                                         export function user(){
                                              try{
                                                   return model('user', new Schema ({
                                                            FirstName: String,
                                                            Last name: String
                                                     }));
                                              }
                                             catch{
                                                   return model('user');
                                              }
                                         }
                                

                                同样你也可以用js写代码。

                                【讨论】:

                                  【解决方案26】:

                                  我通过这样做解决了这个问题

                                  // Created Schema - Users
                                  // models/Users.js
                                  const mongoose = require("mongoose");
                                  
                                  const Schema = mongoose.Schema;
                                  
                                  export const userSchema = new Schema({
                                    // ...
                                  });
                                  

                                  然后在其他文件中

                                  // Another file
                                  // index.js
                                  import { userSchema } from "../models/Users";
                                  const conn = mongoose.createConnection(process.env.CONNECTION_STRING, {
                                      useNewUrlParser: true,
                                      useUnifiedTopology: true,
                                  });
                                  conn.models = {};
                                  const Users = conn.model("Users", userSchema);
                                  const results = await Users.find({});
                                  

                                  更好的解决方案

                                  let User;
                                  try {
                                    User = mongoose.model("User");
                                  } catch {
                                    User = mongoose.model("User", userSchema);
                                  }
                                  

                                  我希望这会有所帮助...

                                  【讨论】:

                                  • 不知道为什么很难提供解释。想象一下,当每个人都阅读您的代码时,您浪费了多少时间。
                                  【解决方案27】:

                                  这可能会给某些人带来打击,但我也遇到了错误,并意识到我只是在导入时拼错了用户模型。

                                  错误:const User = require('./UserModel'); 正确:const User = require('./userModel');

                                  难以置信,但请考虑一下。

                                  【讨论】:

                                  • 似乎是节点中可能存在的错误
                                  【解决方案28】:

                                  您还可以做的是在导出时,确保导出现有实例(如果存在)。

                                  打字稿解决方案:

                                  import { Schema, Document, model, models } from 'mongoose';
                                  
                                  const UserSchema: Schema = new Schema({
                                      name: {
                                          type: String
                                      }
                                  });
                                  
                                  export interface IUser extends Document {
                                      name: string
                                  }
                                  
                                  export default models.Users || model<IUser>('Users', UserSchema);
                                  

                                  【讨论】:

                                    【解决方案29】:

                                    这是发生这种情况的另一个原因。也许这可以帮助别人。请注意区别,会员s 与会员。它们必须相同...

                                    export default mongoose.models.Members || mongoose.model('Member', FamilySchema)
                                    

                                    改为:

                                    export default mongoose.models.Member || mongoose.model('Member', FamilySchema)
                                    

                                    【讨论】:

                                    • 谢谢,这尤其有助于“我认为”开发服务器的热重载,这是我的情况。
                                    【解决方案30】:

                                    就这样导出 export.User = mongoose.models.User || mongoose.model('User', userSchema);

                                    【讨论】:

                                      猜你喜欢
                                      • 2015-04-25
                                      • 2020-05-08
                                      • 2021-05-18
                                      • 2021-07-06
                                      • 2021-03-01
                                      • 2020-10-07
                                      • 2019-01-13
                                      • 2014-08-03
                                      相关资源
                                      最近更新 更多