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" : "[email protected]", 
    "password" : "myPassword", 
    "phone" : 900001123, 
    "_enable" : true 
  } 
>
Anathema. Imbued
sumber
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": "[email protected]", "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); 
});
thtsigma
sumber
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.

jonnie
sumber
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...>)
}
BJ Anderson
sumber
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);
ZephDavies
sumber
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.

munyah
sumber
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);
Julian
sumber
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!

James Harrington
sumber
11

Ini terjadi pada saya ketika saya menulis seperti ini:

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

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

ip192
sumber
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

Toufiq
sumber
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];
}
Alpha BA
sumber
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.

Moosecouture
sumber
2

Masalah ini mungkin terjadi jika Anda menentukan 2 skema berbeda dengan nama Koleksi yang sama

Rohit Reddy Abbadi
sumber
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" } });
Rohit Jangid
sumber
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.

beemaster
sumber
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

Tim
sumber
0

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

KARTHIKEYAN.A
sumber
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);
Diego Santa Cruz MendezĂș
sumber
0

Anda dapat dengan mudah menyelesaikannya dengan melakukan

delete mongoose.connection.models['users'];
const usersSchema = mongoose.Schema({...});
export default mongoose.model('users', usersSchema);
Shyam
sumber
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.

Engr.MTH
sumber
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.
Rohit Jangid
sumber
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");
BeyondTheSea
sumber
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"})
titoih
sumber
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...


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

AKP
sumber
-2

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

David Khan
sumber
-4

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

Elesin Olalekan Fuad
sumber
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