Impossibile sovrascrivere il modello una volta compilato Mongoose


109

Non sono sicuro di cosa sto sbagliando, ecco il mio 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 })
    });

ed ecco il mio 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); 
   });

Ogni volta che provo a eseguire check.js, ricevo questo errore

Non è possibile sovrascrivere il modello "utenti" una volta compilato .

Capisco che questo errore sia dovuto alla mancata corrispondenza dello schema, ma non riesco a vedere dove sta accadendo? Sono abbastanza nuovo per mangusta e nodeJS.

Ecco cosa ottengo dall'interfaccia client del mio 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 
  } 
>

Ecco cosa ottengo dall'interfaccia client del mio MongoDB: Versione shell di MongoDB: 2.4.6 connessione a: test> use event-db passato a db event-db> db.users.find () {"_id": ObjectId ("52457d8718f83293205aaa95"), "name": "MyName", "email": "myemail@me.com", "password": "myPassword", "phone": 900001123, "_enable": true}>
Anatema Inserito il

Risposte:


110

L'errore si verifica perché hai già uno schema definito e quindi stai definendo di nuovo lo schema. In genere, ciò che dovresti fare è istanziare lo schema una volta e poi fare in modo che un oggetto globale lo chiami quando ne ha bisogno.

Per esempio:

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
Evita di esportare / richiedere modelli: se qualcuno ha messaggi refsu altri modelli, questo può portare a un incubo di dipendenza. Usa var User = mongoose.model('user')invece di require.
wprl

1
Può effettivamente essere utile modificare uno schema dopo averlo definito per il test del codice di migrazione dello schema.
Igor Soarez

1
@wprl puoi spiegarlo ulteriormente? perché richiederlo creerebbe problemi?
varuog

Questa risposta è fuorviante. Il fatto è che se esiste solo un'istanza del server mongoDB e più database, se in un'altra app si definisce un database già utilizzato, si ottiene tale errore. Semplicemente così
Carmine Tambascia

174

Quindi un altro motivo per cui potresti ottenere questo errore è se usi lo stesso modello in file diversi ma il tuo require percorso ha un caso diverso. Ad esempio nella mia situazione ho avuto:

require('./models/User') in un file e poi in un altro file in cui avevo bisogno di accedere al modello utente che avevo require('./models/user') .

Immagino che la ricerca di moduli e mongoose lo tratti come un file diverso. Una volta che mi sono assicurato che il caso corrispondesse in entrambi, non era più un problema.


7
Questo è davvero un problema molto complicato: penso che sia specifico del sistema operativo (dovrebbe accadere solo su Mac e Windows poiché FS ignora il caso). Ho avuto questo problema, ma fortunatamente ho visto la tua risposta :) Grazie mille Jonnie!
Miroslav Nedyalkov

6
questo problema si verifica nel mio sistema OS X.
lutaoact

Non avrei mai potuto pensarci, almeno non intuitivamente! grazie
Naveen Attri

Questo era totalmente il mio problema. Non ho mai pensato che il nome del maiuscolo avrebbe mai causato alcun problema.
Sandip Subedi

Questo è stato lo stesso per me. Tutti accolgono OS X e il suo file system (senza maiuscole / minuscole per impostazione predefinita)
mithril_knight

50

Ho avuto questo problema durante il test dell'unità.

La prima volta che chiami la funzione di creazione del modello, mangusta memorizza il modello con la chiave che fornisci (ad esempio "utenti"). Se chiami la funzione di creazione del modello con la stessa chiave più di una volta, mongoose non ti permetterà di sovrascrivere il modello esistente.

Puoi verificare se il modello esiste già in mangusta con:

let users = mongoose.model('users')

Questo genererà un errore se il modello non esiste, quindi puoi avvolgerlo in una prova / cattura per ottenere il modello o crearlo:

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

1
+1 Ho riscontrato lo stesso problema in cui avevo bisogno di impostare una configurazione per un plug-in prima di poter definire il mio schema. Questo non ha funzionato affatto bene con la moka e alla fine ho rinunciato e sono andato con questo approccio try catch
Victor Parmar

Sto usando lo stesso ma viceversa, è malvagio:try exports.getModel = ()-> mongoose.model('User', userSchema) catch err exports.getModel = ()-> mongoose.model('User')
Andi Giga

Grazie buon signore, ho sprecato più di 5 ore su questo problema. Lavoravo con serverless a differenza del server del nodo a cui sono abituato.
mxdi9i7

43

Ho avuto questo problema mentre "guardavo" i test. Quando i test sono stati modificati, l'orologio ha rieseguito i test, ma proprio per questo motivo hanno fallito.

L'ho risolto controllando se il modello esiste, quindi usalo, altrimenti crealo.

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

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

Questo ha funzionato per me. Avevo cambiato module.export = Userin export defaults User. Ho anche dovuto utilizzare refsutenti da altri modelli. Non sono sicuro del motivo per cui il passaggio da module.exportsa ha export defaultcausato questo problema. Tuttavia, questa risposta sembra averlo risolto.
runios

3
a male mongoose.modelsnon esiste, almeno nelle versioni recenti
Pedro Luz

1
Ho avuto lo stesso problema ma l'ho risolto cancellando tutti i modelli prima di tutti i test:for (let model in mongoose.models) delete mongoose.models[model]
E. Sundin

Il mio script di test ha questo aspetto: "test": "NODE_ENV=test mocha --file mocha.config.js --watch"e in quel file js di configurazione ho un before()e after()per gestire l'installazione e lo smontaggio. @ E.Sundin ha fornito la soluzione perfetta qui, e funziona a meraviglia. Grazie!
Brandon Aaskov

21

Ho riscontrato questo problema e non è stato a causa delle definizioni dello schema, ma piuttosto della modalità offline senza server: sono riuscito a risolverlo con questo:

serverless offline --skipCacheInvalidation

Che è menzionato qui https://github.com/dherault/serverless-offline/issues/258

Si spera che questo aiuti qualcun altro che sta costruendo il proprio progetto in modalità serverless e in esecuzione offline.


2
Molto utile. Grazie.
Thanh Truong

2
Ho trovato fastidioso saltare l'invalidazione della cache, ricariche costanti, invece funzionamodule.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
chiesto_io

hai reso la mia giornata
fstasi

Grazie mille!
AndyFaizan

Questo è stato molto utile. Grazie!
ifiok

20

Se stai usando Serverless offline e non vuoi usare --skipCacheInvalidation, puoi usare molto bene:

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

Devi anche usarlo se stai importando un modello dentro un altro, anche con--skipCacheInvalidation
Powderham

1
Questa è la risposta esatta che stavo cercando, da utilizzare in Next.js. Vorrei che fosse più in alto nella pagina!
Brendan Nee

18

Se l'hai fatto qui è possibile che tu abbia avuto lo stesso problema che ho avuto io. Il mio problema era che stavo definendo un altro modello con lo stesso nome . Ho chiamato la mia galleria e il mio modello di file "File". Maledizione, copia e incolla!


11

Questo è successo a me quando scrivo in questo modo:

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

Tuttavia, il vero percorso è "../myUser/User.js"


La combinazione di maiuscole e minuscole dei percorsi dello schema durante l'importazione sembra causare questo problema: verificare che tutti i file che importano lo schema utilizzino lo stesso caso.
Andrew Cupper,

questo ci ha salvato! abbiamo la sensazione che ciò potrebbe essere dovuto all'uso di Windows
Lyka

11

Ho risolto questo problema aggiungendo

mongoose.models = {}

prima della riga:

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

Spero che risolva il tuo problema


Questo è quello che ho fatto e l'ho risolto. mongoose.connection.models = {};
Fortune

6

Per risolvere questo controllo se il modello esiste prima di eseguire la creazione:

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

4

So che esiste una soluzione accettata, ma ritengo che la soluzione attuale produca un sacco di boilerplate solo per poter testare i modelli. La mia soluzione consiste essenzialmente nel prendere il tuo modello e inserirlo in una funzione che restituisce il nuovo modello se il modello non è stato registrato, ma restituisce il modello esistente se lo è.

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

Aprire e chiudere le connessioni ovunque è frustrante e non si comprime bene.

In questo modo se dovessi richiedere al modello due posti diversi o più specificamente nei miei test non otterrei errori e verranno restituite tutte le informazioni corrette.


2

Questo problema potrebbe verificarsi se si definiscono 2 diversi schemi con lo stesso nome di raccolta


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

Ho avuto lo stesso problema, motivo per cui ho definito lo schema un modello in una funzione JS, dovrebbero essere definiti globalmente in un modulo nodo, non in una funzione.


1

C'è un altro modo per generare questo errore.

Tieni presente che il percorso del modello fa distinzione tra maiuscole e minuscole.

In questo esempio simile che coinvolge il modello "Categoria", l'errore è stato generato in queste condizioni:

1) L'istruzione require è stata menzionata in due file: ..category.js e ..index.js 2) Io il primo, il caso era corretto, nel secondo file non era il seguente:

category.js

inserisci qui la descrizione dell'immagine

index.js

inserisci qui la descrizione dell'immagine


0

La definizione dello schema dovrebbe essere univoca per una raccolta, non dovrebbe essere più di uno schema per una raccolta.


0

è perché il tuo schema è già, convalidalo prima di creare un nuovo schema.

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

Puoi facilmente risolverlo facendo

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

0

Ho una situazione in cui devo creare il modello dinamicamente con ogni richiesta e per questo motivo ho ricevuto questo errore, tuttavia, quello che ho usato per risolverlo è utilizzare il metodo deleteModel come segue:

var contentType = 'Product'

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

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

mongoose.deleteModel(contentType);

Spero che questo possa aiutare chiunque.


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

Per tutte le persone che finiscono qui a causa di un codice base con un mix di Typegoose e Mongoose :

Crea una connessione db per ognuno:

Mangusta:

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

Tipo:

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

0

Ho solo un errore di copia e incolla. In una riga avevo lo stesso nome che in un altro modello (modello di annuncio):

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

Corretto è:

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

A proposito, se qualcuno ha "salvataggio automatico" e utilizza l'indice per query come:

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

Deve eliminare l'indice e riscrivere per il modello corretto:

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

0

Ho risolto questo problema in questo modo

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

const Schema = mongoose.Schema;

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

Quindi in altri file

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

Soluzione migliore

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

Spero che aiuti...


Non ho idea del perché sia ​​così difficile fornire spiegazioni. Immagina il tempo che sprechi mentre tutti leggono il tuo codice.
robertfoenix

-1

Poiché questo problema si è verificato perché ho chiamato il modello un'altra volta. Risolvi questo problema avvolgendo il codice del modello nel blocco try catch. il codice dattiloscritto è così -

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

Allo stesso modo puoi anche scrivere codice in js.


-2

Stai utilizzando mongoose.model con lo stesso nome di variabile "utente" in check.js e insert.js.


-4

Se stai lavorando con expressjs, potresti dover spostare la definizione del modello fuori da app.get () in modo che venga chiamata solo una volta quando viene creata un'istanza dello script.


questo non ha senso, i modelli di mangusta sono definiti solo una volta a meno che non ci sia un problema con la denominazione (ad esempio il caso), una volta che viene chiamato per la prima volta viene inizializzato, le richieste future dovrebbero solo ottenere l'istanza e non ripristinarla
jonnie

Questa non è una soluzione.
Prathamesh More
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.