编译猫鼬后无法覆盖模型


109

不确定我在做什么错,这是我的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时,都会出现此错误

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

我知道此错误是由于架构不匹配引起的,但我看不到发生了什么?我对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连接到:测试>使用event-db切换到db event-db> db.users.find(){“ _id”: ObjectId(“ 52457d8718f83293205aaa95”),“名称”:“ MyName”,“电子邮件”:“ myemail@me.com”,“密码”:“ myPassword”,“电话”:900001123,“ _enable”:true}>
Anathema .13年

Answers:


110

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

例如:

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 
  })
});

insert.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); 
});

69
避免导出/要求模型-如果将模型导出ref到其他模型,则可能导致依赖关系的噩梦。使用var User = mongoose.model('user')代替require
wprl 2013年

1
在定义用于测试模式迁移代码的基础上更改模式实际上可能很有用。
伊戈尔·索亚雷斯

1
@wprl您能否进一步解释?为什么要求它会产生问题?
varuog '18 -10-15

这个答案是误导的。事实是,如果只有一个mongoDB服务器实例和多个数据库,那么如果您在另一个应用程序中定义了已经使用的数据库,则会出现这样的错误。就这么简单
Carmine Tambascia

174

因此,出现此错误的另一个原因是,如果在不同的文件中使用相同的模型,但是require路径具有不同的大小写。例如,在我的情况下,我有:

require('./models/User')在一个文件中,然后在另一个文件中,我需要访问我拥有的User模型require('./models/user')

我想查找模块和猫鼬会将其视为另一个文件。一旦我确定两种情况都匹配,就不再是问题。


7
确实,这是一个非常棘手的问题-我认为这是特定于操作系统的(由于FS忽略了这种情况,它仅应在Mac和Windows上发生)。我遇到了这个问题,但是很幸运看到您的回答:)非常感谢Jonnie!
米罗斯拉夫·涅迪亚尔科夫

6
此问题发生在我的OS X系统中。
lutaoact

我可能从来没有想过,至少不是凭直觉!谢谢
Naveen Attri 16'Sep

那完全是我的问题。我从来没有说过大写的名字会引起任何问题。
Sandip Subedi

对我来说也是一样。所有冰雹OS X及其(默认情况下为区分大小写)文件系统
mithril_knight

49

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

第一次调用模型创建功能时,猫鼬会将模型存储在您提供的密钥(例如“用户”)下。如果使用相同的键多次调用模型创建函数,猫鼬将不允许您覆盖现有模型。

您可以使用以下命令检查模型是否已经存在于猫鼬中:

let users = mongoose.model('users')

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

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

1
+1我遇到了同样的问题,在定义架构之前,我需要为插件设置一些配置。这一点在摩卡咖啡中表现不佳,最终我放弃了,只是采用了这种尝试捕获方法
Victor Parmar

我使用的是相同但相反的方法,这很糟糕:try exports.getModel = ()-> mongoose.model('User', userSchema) catch err exports.getModel = ()-> mongoose.model('User')
Andi Giga

谢谢您,先生,在这个问题上浪费了5个多小时。与以前的节点服务器不同,我正在使用无服务器。
mxdi9i7

43

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

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

import mongoose from 'mongoose';
import user from './schemas/user';

export const User = mongoose.models.User || mongoose.model('User', user);

这对我有用。我已将更改module.export = Userexport defaults User。我还不得不refs从其他型号的用户。我不确定为什么从更改module.exportsexport default带来此问题。尽管如此,这个答案似乎已经解决了。
runios '18

3
到坏处mongoose.models,至少在最新版本中不存在
Pedro Luz

1
我遇到了同样的问题,但通过在所有测试之前清除所有模型来解决此问题:for (let model in mongoose.models) delete mongoose.models[model]
E. Sundin

我的测试脚本如下所示:"test": "NODE_ENV=test mocha --file mocha.config.js --watch"在该config js文件中,我有一个before()after()用于处理设置和拆卸。@ E.Sundin在这里提供了完美的解决方案,它就像一个魅力。谢谢!
布兰登·阿斯科夫

21

我一直遇到此问题,这不是因为架构定义,而是由于无服务器脱机模式-我设法用以下方法解决了它:

serverless offline --skipCacheInvalidation

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

希望这对在无服务器上构建项目并以脱机模式运行的其他人有所帮助。


2
很有帮助。谢谢。
Thanh Truong '18

2
我发现跳过高速缓存失效,不断重新加载很烦人,相反,这行得通module.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
ask_io

你决定了我的一天
fstasi '18

太感谢了!
AndyFaizan

这非常有帮助。谢谢!
ifiok

20

如果您正在离线使用无服务器,并且不想使用--skipCacheInvalidation,那么可以很好地使用:

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

如果要将一个模型导入另一个模型,即使--skipCacheInvalidation
Powderham

1
这是我在Next.js中寻找的确切答案。我希望页面上的这个更高!
Brendan Nee

18

如果您在此处完成,则可能是您遇到了与我相同的问题。我的问题是我要定义另一个具有相同名称的模型。我将其画廊称为“文件”。该死,您复制并粘贴!


11

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

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

但是,真正的路径是“ ../myUser/User.js”


导入时混合使用模式路径的大小写似乎会导致此问题-检查所有导入模式的文件都使用相同的大小写。
安德鲁·库珀

这救了我们!我们有一种感觉,这可能是由于使用Windows
Lyka,

11

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

mongoose.models = {}

前行:

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

希望它能解决您的问题


这就是我所做的,并且已解决。mongoose.connection.models = {};
财富

6

要解决此问题,请在执行创建之前检查模型是否存在:

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

4

我知道有一个公认的解决方案,但是我认为当前的解决方案会产生很多样板,以便您可以测试模型。我的解决方案实质上是将您带入模型并将其放置在函数内,如果尚未注册模型,则返回新模型,如果已经注册,则返回现有模型。

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()

整个地方的打开和关闭连接令人沮丧,并且压缩效果不佳。

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



1
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" } });

1

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


1

还有另一种引发此错误的方法。

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

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

1)在两个文件中提到了require语句:..category.js和..index.js 2)我的第一个文件是正确的,在第二个文件中,它不是如下所示:

category.js

在此处输入图片说明

index.js

在此处输入图片说明


0

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


0

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

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);

0

您可以通过以下方式轻松解决此问题

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

0

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

var contentType = 'Product'

var contentSchema = new mongoose.Schema(schema, virtuals);

var model = mongoose.model(contentType, contentSchema);

mongoose.deleteModel(contentType);

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


0
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.

0

对于所有因为混合了TypegooseMongoose的代码库而在这里结束的人们:

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

猫鼬

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

鹅:

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

0

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

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"})

0

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

// 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);
}

我希望这有帮助...


不知道为什么这么难提供解释。想象一下,每个人都阅读您的代码时浪费的时间。
robertfoenix

-1

由于发生此问题是因为再次调用模型。通过将模型代码包装在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编写代码。


-2

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


-4

如果使用expressjs,则可能需要将模型定义移到app.get()之外,因此在实例化脚本时仅将其调用一次。


这是没有道理的,除非命名存在问题(例如case),否则猫鼬模型仅定义一次,一旦首次将其初始化,将来的需求应该只获取实例而不是对其进行实例化
珍妮

这不是解决方案。
Prathamesh更多
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.