Không thể ghi đè mô hình sau khi đã biên dịch Mongoose


109

Không chắc mình đang làm gì sai, đây là séc của tôi.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 })
    });

và đây là insert.js của tôi

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

Bất cứ khi nào tôi cố gắng chạy check.js, tôi đều gặp lỗi này

Không thể ghi đè mô hình 'người dùng' sau khi được biên dịch .

Tôi hiểu rằng lỗi này xảy ra do Lược đồ không khớp, nhưng tôi không thể biết điều này đang xảy ra ở đâu? Tôi khá mới với mongoose và nodeJS.

Đây là những gì tôi nhận được từ giao diện khách hàng của MongoDB của tôi:

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

Đây là những gì tôi nhận được từ giao diện máy khách của MongoDB: phiên bản MongoDB shell: 2.4.6 đang kết nối với: test> use event-db được chuyển sang db event-db> db.users.find () {"_id": ObjectId ("52457d8718f83293205aaa95"), "name": "MyName", "email": "myemail@me.com", "password": "myPassword", "phone": 900001123, "_enable": true}>
Anathema . Thấm vào

Câu trả lời:


110

Lỗi xảy ra bởi vì bạn đã xác định một lược đồ và sau đó bạn đang xác định lại lược đồ. Nói chung, những gì bạn nên làm là khởi tạo giản đồ một lần và sau đó yêu cầu một đối tượng toàn cục gọi nó khi nó cần.

Ví dụ:

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
Tránh xuất / yêu cầu các mô hình - nếu có mô hình nào có refsang các mô hình khác, điều này có thể dẫn đến cơn ác mộng phụ thuộc. Sử dụng var User = mongoose.model('user')thay vì require.
wprl

1
Nó thực sự có thể hữu ích khi thay đổi một Giản đồ sau khi xác định để kiểm tra mã di chuyển lược đồ.
Igor Soarez

1
@wprl bạn có thể vui lòng giải thích thêm được không? tại sao yêu cầu nó sẽ tạo ra vấn đề?
varuog

Câu trả lời này gây hiểu lầm. Thực tế là nếu chỉ có một phiên bản máy chủ mongoDB và nhiều Cơ sở dữ liệu hơn, nếu bạn xác định trong ứng dụng khác cơ sở dữ liệu đã được lấy thì bạn gặp lỗi như vậy. Chỉ đơn giản như vậy
Carmine Tambascia

174

Vì vậy, một lý do khác khiến bạn có thể gặp phải Lỗi này là nếu bạn sử dụng cùng một mô hình trong các tệp khác nhau nhưng requiređường dẫn của bạn có trường hợp khác. Ví dụ trong tình huống của tôi, tôi đã có:

require('./models/User')trong một tệp và sau đó trong một tệp khác mà tôi cần quyền truy cập vào Mô hình người dùng mà tôi có require('./models/user').

Tôi đoán tìm kiếm mô-đun & mongoose đang coi nó như một tệp khác. Khi tôi đã chắc chắn rằng trường hợp phù hợp với cả hai thì nó không còn là vấn đề nữa.


7
Đó thực sự là một vấn đề phức tạp - tôi nghĩ đó là một hệ điều hành cụ thể (nó chỉ xảy ra trên Mac và Windows vì FS bỏ qua trường hợp này). Tôi đã gặp vấn đề này, nhưng may mắn thay đã thấy câu trả lời của bạn :) Cảm ơn rất nhiều Jonnie!
Miroslav Nedyalkov

6
sự cố này xảy ra trong hệ thống OS X của tôi.
lutaoact 18/02/16

Tôi có thể chưa bao giờ nghĩ đến điều đó, ít nhất là không bằng trực giác! cảm ơn
Naveen Attri

Đó hoàn toàn là vấn đề của tôi. Tôi không bao giờ mặc dù có tên trên vỏ bọc sẽ gây ra bất kỳ vấn đề nào.
Sandip Subedi

Điều này cũng tương tự đối với tôi. Tất cả mưa đá OS X và của nó (trường hợp insesitive theo mặc định) hệ thống tập tin
mithril_knight

50

Tôi đã gặp sự cố này trong khi thử nghiệm đơn vị.

Lần đầu tiên bạn gọi hàm tạo mô hình, mongoose sẽ lưu trữ mô hình dưới khóa bạn cung cấp (ví dụ: 'người dùng'). Nếu bạn gọi hàm tạo mô hình bằng cùng một phím nhiều lần, mongoose sẽ không cho phép bạn ghi đè lên mô hình hiện có.

Bạn có thể kiểm tra xem mô hình đã tồn tại trong mongoose hay chưa bằng:

let users = mongoose.model('users')

Điều này sẽ gây ra lỗi nếu mô hình không tồn tại, vì vậy bạn có thể gói nó trong một lần thử / bắt để lấy mô hình hoặc tạo mô hình:

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

1
+1 Tôi đang gặp vấn đề tương tự trong đó tôi cần thiết lập một số cấu hình cho plugin trước khi tôi có thể xác định giản đồ của mình. Điều này đã không chơi tốt với mocha ở tất cả và cuối cùng tôi đã từ bỏ và chỉ đi với cách tiếp cận cố gắng nắm bắt này
Victor Parmar

Tôi đang sử dụng cùng một cách nhưng ngược lại, điều đó thật độc ác:try exports.getModel = ()-> mongoose.model('User', userSchema) catch err exports.getModel = ()-> mongoose.model('User')
Andi Giga.

Cảm ơn bạn tốt, thưa ông, đã lãng phí hơn 5 giờ cho vấn đề này. Tôi đã làm việc với máy chủ không giống như máy chủ nút mà tôi đã quen.
mxdi9i7 13/02/19

43

Tôi đã gặp sự cố này khi 'xem' các bài kiểm tra. Khi các bài kiểm tra được chỉnh sửa, đồng hồ chạy lại các bài kiểm tra, nhưng chúng không thành công do chính lý do này.

Tôi đã sửa nó bằng cách kiểm tra nếu mô hình tồn tại thì hãy sử dụng nó, nếu không hãy tạo nó.

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

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

Điều này đã làm việc cho tôi. Tôi đã thay đổi module.export = Userthành export defaults User. Tôi cũng đã refsphải Người dùng từ các mô hình khác. Tôi không chắc tại sao việc thay đổi từ module.exportssang export defaultlại đưa ra vấn đề này. Tuy nhiên, câu trả lời này dường như đã sửa nó.
runios

3
để xấu mongoose.modelskhông tồn tại, ít nhất là trong các phiên bản gần đây
Pedro Luz

1
Tôi đã cùng một vấn đề nhưng cố định nó với thanh toán bù trừ tất cả các mô hình trước khi tất cả các xét nghiệm:for (let model in mongoose.models) delete mongoose.models[model]
E. Sundin

Tập lệnh thử nghiệm của tôi trông giống như vậy: "test": "NODE_ENV=test mocha --file mocha.config.js --watch"và trong tệp js cấu hình đó, tôi có before()after()để xử lý thiết lập và chia nhỏ. @ E.Sundin đã cung cấp giải pháp hoàn hảo ở đây và nó hoạt động như một sự quyến rũ. Cảm ơn bạn!
Brandon Aaskov

21

Tôi đã gặp phải sự cố này & đó không phải do định nghĩa giản đồ mà là do chế độ ngoại tuyến không có máy chủ - tôi chỉ giải quyết được nó bằng cách này:

serverless offline --skipCacheInvalidation

Được đề cập ở đây https://github.com/dherault/serverless-offline/issues/258

Hy vọng rằng điều đó sẽ giúp những người khác đang xây dựng dự án của họ trên máy chủ và đang chạy chế độ ngoại tuyến.


2
Rất hữu ích. Cảm ơn.
Thanh Truong

2
Tôi thấy thật khó chịu khi bỏ qua việc vô hiệu hóa bộ nhớ cache, tải lại liên tục, thay vào đó điều này hoạt độngmodule.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
ask_io

bạn đã làm nên ngày của tôi
fstasi 23/07/18

Cảm ơn rất nhiều!
AndyFaizan

Điều này rất hữu ích. Cảm ơn bạn!
ifiok

20

Nếu bạn đang sử dụng Serverless ngoại tuyến và không muốn sử dụng --skipCacheInvalidation, bạn rất có thể sử dụng:

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

Bạn cũng cần phải sử dụng này nếu bạn đang nhập khẩu một mô hình bên trong khác, ngay cả với--skipCacheInvalidation
Powderham

1
Đây là câu trả lời chính xác mà tôi đang tìm kiếm, để sử dụng trong Next.js. Tôi ước điều này cao hơn trên trang!
Brendan Nee

18

Nếu bạn thực hiện ở đây, có thể bạn đã gặp phải vấn đề tương tự như tôi đã làm. Vấn đề của tôi là tôi đang xác định một mô hình khác có cùng tên . Tôi đã gọi thư viện và mô hình tệp của mình là "Tệp". Darn bạn sao chép và dán!


11

Điều này đã xảy ra với tôi khi tôi viết như thế này:

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

Tuy nhiên, đường dẫn thực sự là '../myUser/User.js'


Trường hợp trộn lẫn các đường dẫn lược đồ khi nhập dường như gây ra sự cố này - hãy kiểm tra xem tất cả các tệp nhập lược đồ đều sử dụng cùng một trường hợp.
Andrew Cupper

điều này đã cứu chúng tôi! chúng ta có một cảm giác này có thể là do sử dụng cửa sổ
Lyka

11

Tôi đã giải quyết điều này bằng cách thêm

mongoose.models = {}

trước dòng:

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

Hy vọng nó giải quyết được vấn đề của bạn


Đây là những gì tôi đã làm và nó đã sửa nó. mongoose.connection.models = {};
Fortune

6

Để giải quyết vấn đề này, hãy kiểm tra xem mô hình có tồn tại trước đó hay không để thực hiện việc tạo:

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

4

Tôi biết có một giải pháp được chấp nhận nhưng tôi cảm thấy rằng giải pháp hiện tại dẫn đến rất nhiều bản ghi sẵn chỉ để bạn có thể kiểm tra Mô hình. Giải pháp của tôi về cơ bản là đưa bạn mô hình và đặt nó vào bên trong một chức năng dẫn đến trả về Mô hình mới nếu Mô hình chưa được đăng ký nhưng trả về Mô hình hiện có nếu có.

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

Mở và đóng các kết nối khắp nơi là bực bội và không nén tốt.

Bằng cách này nếu tôi yêu cầu mô hình ở hai nơi khác nhau hoặc cụ thể hơn trong các thử nghiệm của mình, tôi sẽ không gặp lỗi và tất cả thông tin chính xác sẽ được trả lại.


2

Sự cố này có thể xảy ra nếu bạn xác định 2 lược đồ khác nhau có cùng tên Bộ sưu tập


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

Tôi đã gặp vấn đề tương tự, lý do là tôi đã xác định lược đồ một mô hình trong một hàm JS, chúng phải được định nghĩa toàn cục trong một mô-đun nút, không phải trong một hàm.


1

Có một cách khác để loại bỏ lỗi này.

Hãy nhớ rằng đường dẫn đến mô hình có phân biệt chữ hoa chữ thường.

Trong ví dụ tương tự này liên quan đến mô hình "Danh mục", lỗi đã xảy ra trong các điều kiện sau:

1) Câu lệnh request đã được đề cập trong hai tệp: ..category.js và ..index.js 2) Tôi là trường hợp đầu tiên, đúng, trong tệp thứ hai, nó không như sau:

category.js

nhập mô tả hình ảnh ở đây

index.js

nhập mô tả hình ảnh ở đây


0

Định nghĩa lược đồ phải là duy nhất cho một tập hợp, không nên có nhiều hơn một lược đồ cho một tập hợp.


0

là do lược đồ của bạn đã có, hãy xác thực trước khi tạo lược đồ mới.

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

Bạn có thể dễ dàng giải quyết vấn đề này bằng cách

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

0

Tôi gặp tình huống phải tạo mô hình động với mỗi yêu cầu và do đó tôi nhận được lỗi này, tuy nhiên, những gì tôi đã sử dụng để khắc phục nó là sử dụng phương thức deleteModel như sau:

var contentType = 'Product'

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

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

mongoose.deleteModel(contentType);

Tôi hy vọng điều này có thể giúp bất kỳ ai.


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

Đối với tất cả những người kết thúc ở đây vì cơ sở mã có sự kết hợp của TypegooseMongoose :

Tạo kết nối db cho từng kết nối:

Mongoose:

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

Typegoose:

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

0

Tôi chỉ có một bản sao dán nhầm. Trong một dòng, tôi có cùng tên trong mô hình khác (Mô hình quảng cáo):

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

Đúng là:

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

Nhân tiện, nếu ai đó có "tự động lưu" và sử dụng chỉ mục cho các truy vấn như:

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

Nó phải xóa chỉ mục và viết lại cho đúng mô hình:

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

0

Tôi đã giải quyết vấn đề này bằng cách làm điều này

// Created Schema - Users
// models/Users.js
const mongoose = require("mongoose");

const Schema = mongoose.Schema;

export const userSchema = new Schema({
  // ...
});

Sau đó, trong các tệp khác

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

Giải pháp tốt hơn

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

Tôi hi vọng cái này giúp được...


Không có manh mối tại sao rất khó để đưa ra lời giải thích. Hãy tưởng tượng thời gian bạn lãng phí khi mọi người đọc qua mã của bạn.
robertfoenix

-1

Kể từ khi vấn đề này xảy ra bởi vì cuộc gọi mô hình lần khác. Khắc phục sự cố này bằng cách gói mã mô hình của bạn trong khối thử bắt. mã typecript như thế này -

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

Tương tự, bạn cũng có thể viết mã bằng js.


-2

Bạn đang sử dụng mongoose.model với cùng một tên biến "user" trong check.js và insert.js.


-4

Nếu đang làm việc với expressj, bạn có thể cần phải di chuyển định nghĩa mô hình của mình ra bên ngoài app.get () để nó chỉ được gọi một lần khi tập lệnh được khởi tạo.


điều này không có ý nghĩa, các mô hình mongoose chỉ được xác định một lần trừ khi có vấn đề với việc đặt tên (ví dụ: trường hợp), khi nó được gọi lần đầu tiên, nó được khởi tạo, yêu cầu trong tương lai chỉ nên lấy phiên bản và không khôi phục nó
jonnie

Đây không phải là một giải pháp.
Prathamesh More
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.