编译Mongoose后无法覆盖模型

时间:2013-09-27 12:41:16

标签: node.js mongodb model express mongoose

不确定我做错了什么,这是我的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 
  } 
>

31 个答案:

答案 0 :(得分:132)

因此,您可能会遇到此错误的另一个原因是,如果您在不同的文件中使用相同的模型,但您的require路径具有不同的情况。例如,在我的情况下,我有:

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

我想要查找模块& mongoose将它视为一个不同的文件。一旦我确定案件在两者中都匹配,就不再是问题。

答案 1 :(得分:82)

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

例如:

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

答案 2 :(得分:32)

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

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

您可以通过以下方式检查模型中是否已存在mongoose:

let users = mongoose.model('users')

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

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

答案 3 :(得分:27)

我在观看&#39;试验。 编辑测试时,手表会重新进行测试,但由于这个原因,测试失败了。

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

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

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

答案 4 :(得分:17)

我一直在遇到这个问题&amp;这不是因为模式定义而是因为无服务器离线模式 - 我只是设法解决它:

serverless offline --skipCacheInvalidation

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

希望这可以帮助正在无服务器上运行并运行脱机模式的其他人。

答案 5 :(得分:11)

如果你在这里做到了,你可能会遇到同样的问题。 我的问题是我正在定义另一个名称相同的模型。 我打电话给我的画廊和我的文件模型“文件”。你复制并粘贴了!

答案 6 :(得分:7)

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

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

然而,真正的道路是&#39; ../ myUser / User.js&#39;

答案 7 :(得分:7)

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

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

答案 8 :(得分:3)

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

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

在整个地方打开和关闭连接令人沮丧,并且压缩不好。

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

答案 9 :(得分:3)

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

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

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

答案 10 :(得分:2)

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

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

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

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

category.js

enter image description here

index.js

enter image description here

答案 11 :(得分:2)

我通过添加

解决了这个问题
mongoose.models = {}

在行之前:

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

希望它可以解决您的问题

答案 12 :(得分: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" } });

答案 13 :(得分:1)

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

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

我希望这对您有帮助...

答案 14 :(得分:1)

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

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

答案 15 :(得分:0)

您还可以在导出时执行操作,请确保导出现有实例(如果存在)。

打字稿解决方案:

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

答案 16 :(得分:0)

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

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

更改为:

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

答案 17 :(得分:0)

像这样出口 exports.User = mongoose.models.User || mongoose.model('User',userSchema);

答案 18 :(得分: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"})

答案 19 :(得分:0)

我在使用 Next.js 和 TypeScript 时遇到了这个问题。最佳答案使得打字不起作用。

这对我有用:

const { Schema } = mongoose

export interface IUser {
  name: string
  email: string
}

const UserSchema = new Schema<IUser>({
  name: { type: String, required: true },
  email: { type: String, required: true },
})

const UserModel = () => mongoose.model<IUser>('User', UserSchema)

export default (mongoose.models.User || UserModel()) as ReturnType<
  typeof UserModel
>

答案 20 :(得分:0)

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

答案 21 :(得分:0)

对于所有因使用 Typegoose Mongoose 混合的代码库而在此处结尾的人:

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

猫鼬:

proxy = new BrowserMobProxyServer();
                proxy.start();
                proxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
                String hostIp = Inet4Address.getLocalHost().getHostAddress();
                Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
//                seleniumProxy.setHttpProxy(hostIp + ":" + proxy.getPort());
//                seleniumProxy.setSslProxy((hostIp + ":" + proxy.getPort()));


                proxy.blacklistRequests("https?:\\/\\/.*\\.google-analytics\\.com\\/.*", 410);
                proxy.blacklistRequests("https:\\/\\/radar\\.cedexis\\.com\\/.*", 410);
                proxy.blacklistRequests("https:\\/\\/www\\.linkedin\\.com\\/li\\/track",410);
                proxy.blacklistRequests("https:\\/\\/www.facebook.com\\/api\\/.*",410);

Typegoose:

nightmare
        .filter({
            urls: [ 'http://apps.istanbulsaglik.gov.tr/Eczane/scripts/bootstrap.min.js',
                'http://apps.istanbulsaglik.gov.tr/Eczane/scripts/modernizr-2.8.3.js',
                'http://apps.istanbulsaglik.gov.tr/Eczane/Content/Site.css',
                'http://apps.istanbulsaglik.gov.tr/Eczane/Content/bootstrap.css',
                'http://apps.istanbulsaglik.gov.tr/Eczane/Content/bootstrap.min.css',
            'http://apps.istanbulsaglik.gov.tr/Eczane/Content/dist/css/bootstrap.css',
            'http://apps.istanbulsaglik.gov.tr/Eczane/Content/less/*.less',
            'https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css',
            'https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/fonts/fontawesome-webfont.woff2?v=4.5.0']
        }

答案 22 :(得分: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.

答案 23 :(得分:0)

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

var contentType = 'Product'

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

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

mongoose.deleteModel(contentType);

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

答案 24 :(得分:0)

您可以通过

轻松解决此问题
delete mongoose.connection.models['users'];
const usersSchema = mongoose.Schema({...});
export default mongoose.model('users', usersSchema);

答案 25 :(得分: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);

答案 26 :(得分:0)

如果您使用相同的集合名称

定义2个不同的架构,则可能会出现此问题

答案 27 :(得分:0)

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

答案 28 :(得分:-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编写代码。

答案 29 :(得分:-2)

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

答案 30 :(得分:-4)

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