Das einmal kompilierte Modell Mongoose kann nicht überschrieben werden


109

Nicht sicher, was ich falsch mache, hier ist meine 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 })
    });

und hier ist meine 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); 
   });

Immer wenn ich versuche, check.js auszuführen, wird dieser Fehler angezeigt

Das einmal kompilierte Benutzermodell kann nicht überschrieben werden .

Ich verstehe, dass dieser Fehler auf eine Nichtübereinstimmung des Schemas zurückzuführen ist, aber ich kann nicht sehen, wo dies geschieht. Ich bin ziemlich neu in Mungo und NodeJS.

Folgendes erhalte ich von der Client-Oberfläche meiner 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 
  } 
>

Folgendes erhalte ich von der Client-Oberfläche meiner MongoDB: MongoDB-Shell-Version: 2.4.6 Verbindung zu: test> use event-db auf db umschalten event-db> db.users.find () {"_id": ObjectId ("52457d8718f83293205aaa95"), "name": "MyName", "email": "myemail@me.com", "password": "myPassword", "phone": 900001123, "_enable": true}>
Anathema .Imbued

Antworten:


109

Der Fehler tritt auf, weil Sie bereits ein Schema definiert haben und das Schema dann erneut definieren. Im Allgemeinen sollten Sie das Schema einmal instanziieren und dann von einem globalen Objekt aufrufen lassen, wenn es benötigt wird.

Beispielsweise:

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
Vermeiden Sie das Exportieren / Erfordernis von Modellen. Wenn Sie Modelle reffür andere Modelle haben, kann dies zu einem Albtraum der Abhängigkeit führen. Verwenden Sie var User = mongoose.model('user')anstelle von require.
wprl

1
Es kann tatsächlich nützlich sein, ein Schema nach dem Definieren zum Testen des Schemamigrationscodes zu ändern.
Igor Soarez

1
@wprl kannst du es bitte weiter erklären? Warum sollte es problematisch sein, wenn man es benötigt?
Varuog

Diese Antwort ist irreführend. Tatsache ist, dass wenn es nur eine mongoDB-Serverinstanz und mehrere Datenbanken gibt, wenn Sie in einer anderen App die bereits genommene Datenbank definieren, ein solcher Fehler auftritt. Einfach so
Carmine Tambascia

174

Ein weiterer Grund, warum dieser Fehler auftreten kann, ist, dass Sie dasselbe Modell in verschiedenen Dateien verwenden, Ihr requirePfad jedoch einen anderen Fall hat. Zum Beispiel hatte ich in meiner Situation:

require('./models/User')in einer Datei und dann in einer anderen Datei, in der ich Zugriff auf das Benutzermodell benötigte, das ich hatte require('./models/user').

Ich denke, die Suche nach Modulen und Mungos behandelt es als eine andere Datei. Nachdem ich sichergestellt hatte, dass der Fall in beiden Fällen übereinstimmte, war dies kein Problem mehr.


7
Das ist in der Tat ein sehr kniffliges Problem - ich denke, es ist betriebssystemspezifisch (es sollte nur unter Mac und Windows auftreten, da der FS den Fall ignoriert). Ich hatte dieses Problem, aber zum Glück sah ich Ihre Antwort :) Vielen Dank Jonnie!
Miroslav Nedyalkov

6
Dieses Problem tritt in meinem OS X-System auf.
Lutaoact

Ich hätte nie daran denken können, zumindest nicht intuitiv! danke
Naveen Attri

Das war genau das, was mein Problem war. Ich hätte nie gedacht, dass ein Name in einem oberen Gehäuse jemals ein Problem verursachen würde.
Sandip Subedi

Das war auch bei mir so. Alle begrüßen OS X und sein Dateisystem (standardmäßig ohne Berücksichtigung der Groß- / Kleinschreibung)
mithril_knight

49

Ich hatte dieses Problem beim Unit-Test.

Wenn Sie die Modellerstellungsfunktion zum ersten Mal aufrufen, speichert Mungo das Modell unter dem von Ihnen angegebenen Schlüssel (z. B. "Benutzer"). Wenn Sie die Modellerstellungsfunktion mehrmals mit demselben Schlüssel aufrufen, können Sie mit Mungo das vorhandene Modell nicht überschreiben.

Sie können überprüfen, ob das Modell bereits im Mungo vorhanden ist mit:

let users = mongoose.model('users')

Dies löst einen Fehler aus, wenn das Modell nicht vorhanden ist. Sie können es also in einen Versuch / Fang einschließen, um entweder das Modell abzurufen oder es zu erstellen:

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

1
+1 Ich hatte das gleiche Problem, bei dem ich eine Konfiguration für ein Plugin einrichten musste, bevor ich mein Schema definieren konnte. Dies spielte überhaupt nicht gut mit Mokka und am Ende gab ich auf und ging einfach mit diesem Versuch Fang Ansatz
Victor Parmar

Ich benutze das gleiche, aber umgekehrt, das ist böse:try exports.getModel = ()-> mongoose.model('User', userSchema) catch err exports.getModel = ()-> mongoose.model('User')
Andi Giga

Vielen Dank, mein Herr, ich habe mehr als 5 Stunden mit diesem Problem verschwendet. Ich habe mit Serverless gearbeitet, im Gegensatz zu Node Server, an die ich gewöhnt bin.
mxdi9i7

43

Ich hatte dieses Problem beim "Anschauen" von Tests. Als die Tests bearbeitet wurden, führte die Uhr die Tests erneut aus, sie schlugen jedoch aus genau diesem Grund fehl.

Ich habe es behoben, indem ich überprüft habe, ob das Modell vorhanden ist, und es dann verwendet habe, sonst habe ich es erstellt.

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

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

Das hat bei mir funktioniert. Ich hatte änderte sich das module.export = Userzu export defaults User. Ich musste refsauch User von anderen Modellen. Ich bin mir nicht sicher, warum der Wechsel von module.exportszu export defaultdieses Problem gebracht hat. Trotzdem scheint diese Antwort es behoben zu haben.
Runios

3
zu schlecht mongoose.modelsexistiert nicht, zumindest in neueren Versionen
Pedro Luz

1
Ich hatte das gleiche Problem, aber es wurde behoben, indem alle Modelle vor allen Tests for (let model in mongoose.models) delete mongoose.models[model]
E. Sundin

Mein "test": "NODE_ENV=test mocha --file mocha.config.js --watch"Testskript sieht so aus: und in dieser Konfigurations-JS-Datei habe ich ein before()und after(), um Setup und Teardown zu handhaben. @ E.Sundin bot hier die perfekte Lösung, und es funktioniert wie ein Zauber. Danke dir!
Brandon Aaskov

21

Ich habe dieses Problem festgestellt und es lag nicht an den Schemadefinitionen, sondern am serverlosen Offline-Modus. Ich habe es nur so gelöst:

serverless offline --skipCacheInvalidation

Was hier erwähnt wird https://github.com/dherault/serverless-offline/issues/258

Hoffentlich hilft das jemand anderem, der sein Projekt im Serverless-Modus erstellt und den Offline-Modus ausführt.


2
Sehr hilfreich. Vielen Dank.
Thanh Truong

2
Ich fand es ärgerlich, die Ungültigmachung des Caches zu überspringen, ständig neu zu laden, stattdessen funktioniert diesmodule.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
ask_io

Du hast meinen Tag gemacht
fstasi

Tausend Dank!
AndyFaizan

Das war sehr hilfreich. Danke dir!
Ifiok

20

Wenn Sie Serverless offline verwenden und nicht verwenden möchten --skipCacheInvalidation, können Sie Folgendes verwenden:

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

Sie müssen dies auch verwenden, wenn Sie ein Modell in ein anderes importieren, auch mit--skipCacheInvalidation
Powderham

1
Dies ist die genaue Antwort, nach der ich gesucht habe, um sie in Next.js zu verwenden. Ich wünschte, das wäre weiter oben auf der Seite!
Brendan Nee

18

Wenn Sie es hier geschafft haben, ist es möglich, dass Sie das gleiche Problem hatten, das ich hatte. Mein Problem war, dass ich ein anderes Modell mit dem gleichen Namen definierte . Ich habe meine Galerie und mein Dateimodell "Datei" genannt. Verdammt, du kopierst und fügst ein!


11

Das ist mir passiert, wenn ich so schreibe:

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

Der wahre Pfad lautet jedoch '../myUser/User.js'.


Das Mischen der Groß- und Kleinschreibung von Schemapfaden beim Importieren scheint dieses Problem zu verursachen. Überprüfen Sie, ob alle Dateien, die das Schema importieren, denselben Fall verwenden.
Andrew Cupper

das hat uns gerettet! Wir haben das Gefühl, dass dies an der Verwendung von Windows liegen könnte
Lyka

11

Ich habe dies durch Hinzufügen gelöst

mongoose.models = {}

vor der Zeile:

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

Hoffe, es löst Ihr Problem


Das habe ich getan und es hat es behoben. mongoose.connection.models = {};
Fortune

6

So lösen Sie dieses Problem: Überprüfen Sie, ob das Modell vor der Erstellung vorhanden ist:

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

4

Ich weiß, dass es eine akzeptierte Lösung gibt, aber ich bin der Meinung, dass die aktuelle Lösung zu einer Menge Boilerplate führt, nur damit Sie Modelle testen können. Meine Lösung besteht im Wesentlichen darin, Ihr Modell in eine Funktion zu platzieren, die zur Rückgabe des neuen Modells führt, wenn das Modell nicht registriert wurde, aber das vorhandene Modell zurückgibt, wenn dies der Fall ist.

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

Das Öffnen und Schließen von Verbindungen überall ist frustrierend und lässt sich nicht gut komprimieren.

Auf diese Weise würde ich keine Fehler erhalten, wenn ich das Modell an zwei verschiedenen Stellen oder genauer in meinen Tests benötigen würde, und alle korrekten Informationen werden zurückgegeben.


2

Dieses Problem kann auftreten, wenn Sie zwei verschiedene Schemas mit demselben Sammlungsnamen definieren


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

Ich hatte das gleiche Problem. Grund dafür war, dass ich ein Schema für ein Modell in einer JS-Funktion definiert habe. Sie sollten global in einem Knotenmodul und nicht in einer Funktion definiert werden.


1

Es gibt eine andere Möglichkeit, diesen Fehler auszulösen.

Beachten Sie, dass beim Pfad zum Modell zwischen Groß- und Kleinschreibung unterschieden wird.

In diesem ähnlichen Beispiel mit dem Modell "Kategorie" wurde der Fehler unter folgenden Bedingungen ausgelöst:

1) Die require-Anweisung wurde in zwei Dateien erwähnt: ..category.js und ..index.js 2) In der ersten war der Fall korrekt, in der zweiten Datei war es nicht wie folgt:

category.js

Geben Sie hier die Bildbeschreibung ein

index.js

Geben Sie hier die Bildbeschreibung ein


0

Die Schemadefinition sollte für eine Sammlung eindeutig sein. Sie sollte nicht mehr als ein Schema für eine Sammlung sein.


0

Weil Ihr Schema bereits vorhanden ist, überprüfen Sie es, bevor Sie ein neues Schema erstellen.

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

Sie können dies leicht lösen, indem Sie dies tun

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

0

Ich habe eine Situation, in der ich das Modell bei jeder Anforderung dynamisch erstellen muss, und aus diesem Grund habe ich diesen Fehler erhalten. Um ihn zu beheben, habe ich jedoch die Methode deleteModel wie die folgende verwendet:

var contentType = 'Product'

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

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

mongoose.deleteModel(contentType);

Ich hoffe das konnte jedem helfen.


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

Für alle Leute, die wegen einer Codebasis mit einer Mischung aus Typegoose und Mongoose hier enden :

Erstellen Sie für jede eine Datenbankverbindung:

Mungo:

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

Tippfehler:

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

0

Ich habe nur eine fehlerhafte Kopie eingefügt. In einer Zeile hatte ich den gleichen Namen wie in einem anderen Modell (Anzeigenmodell):

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

Richtig ist:

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

Übrigens, wenn jemand "automatisch speichern" hat und Index für Abfragen verwendet wie:

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

Es muss den Index löschen und für das richtige Modell neu schreiben:

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

0

Ich habe dieses Problem dadurch gelöst

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

const Schema = mongoose.Schema;

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

Dann in anderen Dateien

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

Bessere Lösung

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

Ich hoffe das hilft...


Keine Ahnung, warum es so schwierig ist, Erklärungen abzugeben. Stellen Sie sich die Zeit vor, die Sie verschwenden, wenn alle Ihren Code lesen.
robertfoenix vor

-1

Da dieses Problem aufgetreten ist, weil das Modell ein anderes Mal aufgerufen wurde. Umgehen Sie dieses Problem, indem Sie Ihren Modellcode in den try catch-Block einschließen. Typoskript-Code ist wie folgt:

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

Ebenso können Sie auch Code in js schreiben.


-2

Sie verwenden mongoose.model mit demselben Variablennamen "user" in check.js und insert.js.


-4

Wenn Sie mit expressjs arbeiten, müssen Sie Ihre Modelldefinition möglicherweise außerhalb von app.get () verschieben, damit sie nur einmal aufgerufen wird, wenn das Skript instanziiert wird.


Dies ist nicht sinnvoll. Mungomodelle werden nur einmal definiert, es sei denn, es liegt ein Problem mit der Benennung vor (z. B. case). Sobald sie zum ersten Mal aufgerufen wird, sollten zukünftige Anforderungen nur die Instanz erhalten und sie nicht erneut aktivieren
jonnie

Dies ist keine Lösung.
Prathamesh More
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.