Tidak dapat menimpa model setelah dikompilasi Mongoose


109

Tidak yakin apa yang saya lakukan salah, ini check.js saya

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

dan inilah insert.js saya

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

Setiap kali saya mencoba menjalankan check.js, saya mendapatkan kesalahan ini

Tidak dapat menimpa model 'pengguna' setelah dikompilasi .

Saya memahami bahwa kesalahan ini terjadi karena ketidakcocokan Skema, tetapi saya tidak dapat melihat di mana ini terjadi? Saya cukup baru mengenal luwak dan nodeJS.

Inilah yang saya dapatkan dari antarmuka klien MongoDB saya:

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

Inilah yang saya dapatkan dari antarmuka klien MongoDB saya: versi shell MongoDB: 2.4.6 menghubungkan ke: test> gunakan event-db dialihkan ke db event-db> db.users.find () {"_id": ObjectId ("52457d8718f83293205aaa95"), "name": "MyName", "email": "myemail@me.com", "password": "myPassword", "phone": 900001123, "_enable": true}>
Anathema Dibangun

Jawaban:


110

Kesalahan ini terjadi karena Anda sudah menetapkan skema, lalu Anda menetapkan skema lagi. Umumnya yang harus Anda lakukan adalah membuat instance skema satu kali, dan kemudian meminta objek global untuk memanggilnya saat diperlukan.

Sebagai contoh:

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
Hindari mengekspor / memerlukan model - jika ada yang harus refke model lain, ini dapat menyebabkan mimpi buruk ketergantungan. Gunakan var User = mongoose.model('user')sebagai ganti require.
wprl

1
Sebenarnya berguna untuk mengubah Skema setelah menentukan untuk menguji kode migrasi skema.
Igor Soarez

1
@wprl bisa tolong jelaskan lebih lanjut? mengapa membutuhkannya menimbulkan masalah?
varuog

Jawaban ini menyesatkan. Faktanya adalah bahwa jika hanya ada satu instance server mongoDB dan lebih banyak Database, jika Anda menentukan di aplikasi lain database sudah diambil, maka Anda mendapatkan kesalahan seperti itu. Sesederhana itu
Carmine Tambascia

174

Jadi Alasan Lain mengapa Anda mungkin mendapatkan Kesalahan ini adalah jika Anda menggunakan model yang sama di file yang berbeda tetapi requirejalur Anda memiliki kasus yang berbeda. Misalnya dalam situasi saya, saya memiliki:

require('./models/User')dalam satu file dan kemudian di file lain di mana saya membutuhkan akses ke model Pengguna yang saya miliki require('./models/user').

Saya kira mencari modul & luwak memperlakukannya sebagai file yang berbeda. Setelah saya memastikan bahwa kasusnya cocok di keduanya, itu tidak lagi menjadi masalah.


7
Itu memang masalah yang sangat rumit - saya pikir ini adalah OS khusus (seharusnya hanya terjadi di Mac dan Windows karena FS mengabaikan kasus ini). Saya punya masalah ini, tapi untungnya melihat jawaban Anda :) Terima kasih banyak Jonnie!
Miroslav Nedyalkov

6
masalah ini terjadi di sistem OS X saya.
lutaoact

Saya tidak pernah bisa memikirkannya, setidaknya tidak secara intuitif! terima kasih
Naveen Attri

Itu benar-benar masalah saya. Saya tidak pernah berpikir memiliki kotak atas bernama akan menimbulkan masalah.
Sandip Subedi

Ini sama bagiku. Semua hail OS X dan sistem file (case insesitive secara default)
mithril_knight

50

Saya mengalami masalah ini saat pengujian unit.

Pertama kali Anda memanggil fungsi pembuatan model, luwak menyimpan model di bawah kunci yang Anda berikan (mis. 'Pengguna'). Jika Anda memanggil fungsi pembuatan model dengan kunci yang sama lebih dari sekali, luwak tidak akan membiarkan Anda menimpa model yang ada.

Anda dapat memeriksa apakah model tersebut sudah ada di luwak dengan:

let users = mongoose.model('users')

Ini akan memunculkan kesalahan jika model tidak ada, sehingga Anda dapat membungkusnya dengan mencoba / menangkap untuk mendapatkan model, atau membuatnya:

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

1
+1 Saya mengalami masalah yang sama saat saya perlu menyiapkan beberapa konfigurasi untuk plugin sebelum saya dapat menentukan skema saya. Ini tidak cocok dengan moka sama sekali dan pada akhirnya saya menyerah dan hanya menggunakan pendekatan coba tangkap ini
Victor Parmar

Saya menggunakan yang sama tetapi sebaliknya, itu jahat:try exports.getModel = ()-> mongoose.model('User', userSchema) catch err exports.getModel = ()-> mongoose.model('User')
Andi Giga

Terima kasih tuan yang baik, membuang 5+ jam untuk masalah ini. Saya bekerja dengan serverless tidak seperti server node yang biasa saya gunakan.
mxdi9i7

43

Saya mengalami masalah ini saat 'menonton' tes. Ketika tes diedit, jam tangan menjalankan kembali tes, tetapi gagal karena alasan ini.

Saya memperbaikinya dengan memeriksa apakah modelnya ada, lalu gunakan, jika tidak buatlah.

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

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

Ini berhasil untuk saya. Saya telah mengubah module.export = Usermenjadi export defaults User. Saya juga harus refsPengguna dari model lain. Saya tidak yakin mengapa mengubah dari module.exportsmenjadi export defaultmembawa masalah ini. Namun demikian, jawaban ini tampaknya telah memperbaikinya.
runios

3
buruk mongoose.modelstidak ada, setidaknya dalam versi terbaru
Pedro Luz

1
Saya memiliki masalah yang sama tetapi memperbaikinya dengan menghapus semua model sebelum semua tes:for (let model in mongoose.models) delete mongoose.models[model]
E. Sundin

Skrip pengujian saya terlihat seperti ini: "test": "NODE_ENV=test mocha --file mocha.config.js --watch"dan dalam file config js saya memiliki before()dan after()untuk menangani penyiapan dan pembongkaran. @ E.Sundin memberikan solusi sempurna di sini, dan berfungsi dengan sangat baik. Terima kasih!
Brandon Aaskov

21

Saya telah mengalami masalah ini & itu bukan karena definisi skema melainkan mode offline tanpa server - Saya baru saja berhasil menyelesaikannya dengan ini:

serverless offline --skipCacheInvalidation

Yang disebutkan di sini https://github.com/dherault/serverless-offline/issues/258

Mudah-mudahan itu membantu orang lain yang sedang membangun proyek mereka tanpa server dan menjalankan mode offline.


2
Sangat membantu. Terima kasih.
Thanh Truong

2
Saya merasa menjengkelkan untuk melewatkan pembatalan cache, memuat ulang terus-menerus, alih-alih ini berfungsimodule.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
ask_io

Anda membuat hari saya menyenangkan
fstasi

Terima kasih banyak!
AndyFaizan

Ini sangat membantu. Terima kasih!
ifiok

20

Jika Anda menggunakan Serverless offline dan tidak ingin menggunakan --skipCacheInvalidation, Anda dapat menggunakan:

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

Anda juga harus menggunakan ini jika Anda mengimpor satu model ke dalam model lain, bahkan dengan--skipCacheInvalidation
Powderham

1
Ini adalah jawaban yang tepat yang saya cari, untuk digunakan di Next.js. Saya berharap ini lebih tinggi di halaman!
Brendan Nee

18

Jika Anda membuatnya di sini, mungkin Anda memiliki masalah yang sama dengan yang saya alami. Masalah saya adalah saya mendefinisikan model lain dengan nama yang sama . Saya menyebut galeri dan model file saya "File". Sialan Anda salin dan tempel!


11

Ini terjadi pada saya ketika saya menulis seperti ini:

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

Namun, jalur sebenarnya adalah '../myUser/User.js'


Kasus pencampuran jalur skema saat mengimpor tampaknya menyebabkan masalah ini - periksa apakah semua file yang mengimpor skema menggunakan kasus yang sama.
Andrew Cupper

ini menyelamatkan kita! kami merasa ini mungkin karena menggunakan windows
Lyka

11

Saya menyelesaikan ini dengan menambahkan

mongoose.models = {}

sebelum garis:

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

Semoga ini menyelesaikan masalah Anda


Inilah yang saya lakukan dan itu memperbaikinya. mongoose.connection.models = {};
Keberuntungan

6

Untuk memecahkan ini, periksa apakah model tersebut sudah ada sebelumnya untuk melakukan pembuatan:

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

4

Saya tahu ada solusi yang diterima tetapi saya merasa bahwa solusi saat ini menghasilkan banyak boilerplate hanya sehingga Anda dapat menguji Model. Solusi saya pada dasarnya adalah membawa Anda model dan meletakkannya di dalam fungsi yang menghasilkan pengembalian Model baru jika Model belum terdaftar tetapi mengembalikan Model yang ada jika sudah.

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

Membuka dan menutup koneksi di semua tempat membuat frustrasi dan tidak terkompresi dengan baik.

Dengan cara ini jika saya memerlukan model dua tempat yang berbeda atau lebih khusus dalam pengujian saya, saya tidak akan mendapatkan kesalahan dan semua informasi yang benar dikembalikan.



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

Saya memiliki masalah yang sama, alasannya adalah saya mendefinisikan skema model dalam fungsi JS, mereka harus didefinisikan secara global dalam modul node, bukan dalam fungsi.


1

Ada cara lain untuk mengatasi kesalahan ini.

Perlu diingat bahwa jalur ke model peka huruf besar / kecil.

Dalam contoh serupa yang melibatkan model "Kategori", kesalahan terjadi dalam kondisi berikut:

1) Pernyataan yang diminta disebutkan dalam dua file: ..category.js dan ..index.js 2) Saya yang pertama, kasusnya benar, di file kedua tidak seperti berikut:

category.js

masukkan deskripsi gambar di sini

index.js

masukkan deskripsi gambar di sini


0

Definisi skema harus unik untuk koleksi, tidak boleh lebih dari satu skema untuk koleksi.


0

karena skema Anda sudah, validasi sebelum membuat skema baru.

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

Anda dapat dengan mudah menyelesaikannya dengan melakukan

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

0

Saya mengalami situasi di mana saya harus membuat model secara dinamis dengan setiap permintaan dan karena itu saya menerima kesalahan ini, namun, yang saya gunakan untuk memperbaikinya menggunakan metode deleteModel seperti berikut:

var contentType = 'Product'

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

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

mongoose.deleteModel(contentType);

Saya harap ini bisa membantu siapa saja.


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

Untuk semua orang yang berakhir di sini karena basis kode dengan campuran Typegoose dan Mongoose :

Buat koneksi db untuk masing-masing:

Luwak:

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

Jenis kambing:

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

0

Saya hanya memiliki kesalahan saat menyalin. Dalam satu baris saya memiliki nama yang sama dengan model lain (Model iklan):

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

Benar adalah:

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

Omong-omong, jika seseorang memiliki "simpan otomatis", dan gunakan indeks untuk kueri seperti:

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

Itu harus menghapus indeks, dan menulis ulang untuk model yang benar:

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

0

Saya memecahkan masalah ini dengan melakukan ini

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

const Schema = mongoose.Schema;

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

Kemudian di file lainnya

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

Solusi yang Lebih Baik

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

Saya harap ini membantu...


Tidak ada petunjuk mengapa begitu sulit memberikan penjelasan. Bayangkan waktu yang Anda buang saat semua orang membaca kode Anda.
robertfoenix

-1

Karena masalah ini terjadi karena memanggil model di lain waktu. Atasi masalah ini dengan membungkus kode model Anda di blok coba tangkap. kode ketikan seperti ini -

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

Demikian pula Anda dapat menulis kode di js juga.


-2

Anda menggunakan mongoose.model dengan nama variabel yang sama "user" di check.js dan insert.js.


-4

Jika Anda bekerja dengan expressjs, Anda mungkin perlu memindahkan definisi model Anda ke luar app.get () sehingga hanya dipanggil sekali ketika skrip dibuat.


ini tidak masuk akal, model luwak hanya didefinisikan sekali kecuali ada masalah dengan penamaan (misalnya kasus), setelah pertama kali dipanggil itu dimulai, masa depan membutuhkan hanya mendapatkan contoh dan tidak memulihkannya
jonnie

Ini bukan solusi.
Prathamesh More
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.