Mongoose derlendikten sonra modelin üzerine yazılamaz


109

Neyi yanlış yaptığımdan emin değilim, işte 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 })
    });

ve işte benim 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); 
   });

Check.js'yi ne zaman çalıştırmaya çalışsam, bu hatayı alıyorum

Derlendikten sonra 'kullanıcılar' modelinin üzerine yazılamaz .

Bu hatanın Schema uyuşmazlığından kaynaklandığını anlıyorum, ancak bunun nerede olduğunu göremiyorum? Firavun faresi ve nodeJS konusunda oldukça yeniyim.

MongoDB'min istemci arayüzünden aldığım şey şu:

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

MongoDB'min istemci arayüzünden aldığım şey şu: MongoDB kabuk sürümü: 2.4.6 bağlanıyor: test> db event-db> db.users.find () {"_id" olarak değiştirilen event-db kullan: ObjectId ("52457d8718f83293205aaa95"), "name": "MyName", "email": "myemail@me.com", "password": "myPassword", "phone": 900001123, "_enable": true}>
Anathema

Yanıtlar:


110

Hata, zaten tanımlanmış bir şemanız olduğundan ve ardından şemayı yeniden tanımladığınız için ortaya çıkıyor. Genel olarak yapmanız gereken, şemayı bir kez somutlaştırmak ve ardından ihtiyaç duyduğunda global bir nesnenin onu çağırmasını sağlamaktır.

Örneğin:

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
Modelleri dışa aktarmaktan / zorunlu kılmaktan kaçının - eğer varsa refdiğer modellere e-posta adresleri varsa, bu bir bağımlılık kabusuna yol açabilir. var User = mongoose.model('user')Bunun yerine kullanın require.
wprl

1
Şema geçiş kodunu test etmek için tanımladıktan sonra bir Şemayı değiştirmek aslında faydalı olabilir.
Igor Soarez

1
@wprl biraz daha açıklar mısınız? neden onu zorunlu kılmak sorun yaratır?
varuog

Bu cevap yanıltıcıdır. Gerçek şu ki, yalnızca bir mongoDB sunucu örneği ve daha fazla Veritabanı varsa, başka bir uygulamada önceden alınmış bir veritabanını tanımlarsanız, o zaman böyle bir hatayla karşılaşırsınız. Basitçe böyle
Carmine Tambascia

174

Öyleyse, bu Hatayı almanızın başka bir nedeni, aynı modeli farklı dosyalarda kullanıyorsanız, ancak yolunuzun requirefarklı bir durumu varsa. Örneğin benim durumumda:

require('./models/User')bir dosyada ve sonra sahip olduğum Kullanıcı modeline erişmem gereken başka bir dosyada require('./models/user').

Sanırım modüller ve firavun faresi araması onu farklı bir dosya olarak ele alıyor. Davanın her ikisiyle de eşleştiğinden emin olduktan sonra artık sorun olmaktan çıktı.


7
Bu gerçekten çok zor bir sorundur - bence işletim sistemine özgüdür (FS'nin durumu görmezden gelmesi nedeniyle bu yalnızca Mac ve Windows'ta gerçekleşmelidir). Bu problemi yaşadım ama neyse ki cevabınızı gördüm :) Çok teşekkürler Jonnie!
Miroslav Nedyalkov

6
bu sorun OS X sistemimde oluyor.
lutaoact

Bunu asla düşünemezdim, en azından sezgisel olarak! teşekkürler
Naveen Attri

Benim sorunum da buydu. Hiçbir zaman üst kasaya sahip olmanın herhangi bir soruna yol açacağını düşünmedim.
Sandip Subedi

Bu benim için aynıydı. Tüm dolu OS X ve (varsayılan olarak büyük / küçük harf duyarlı) dosya sistemi
mithril_knight

50

Birim test ederken bu sorunu yaşadım.

Model oluşturma işlevini ilk kez çağırdığınızda, mongoose modeli sağladığınız anahtarın (örneğin, 'kullanıcılar') altında depolar. Aynı anahtarla model oluşturma işlevini birden fazla çağırırsanız, firavun faresi mevcut modelin üzerine yazmanıza izin vermez.

Modelin halihazırda firavun faresinde olup olmadığını kontrol edebilirsiniz:

let users = mongoose.model('users')

Bu, model mevcut değilse bir hata verecektir, böylece modeli almak veya oluşturmak için onu dene / yakala'ya sarabilirsiniz:

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

1
+1 Şemamı tanımlamadan önce bir eklenti için bazı yapılandırmalar kurmam gerektiğinde aynı sorunu yaşıyordum. Bu, mocha ile hiç iyi oynamadı ve sonunda pes ettim ve bu deneme yakalama yaklaşımına gittim
Victor Parmar

Ben de aynısını kullanıyorum ama tam tersi, bu çok kötü:try exports.getModel = ()-> mongoose.model('User', userSchema) catch err exports.getModel = ()-> mongoose.model('User')
Andi Giga

Teşekkür ederim, efendim, bu problem için 5+ saat harcadım. Alışık olduğum düğüm sunucusunun aksine sunucusuz çalışıyordum.
mxdi9i7

43

Bu sorunu testleri 'izlerken' yaşadım. Testler düzenlendiğinde saat testleri tekrar yaptı, ancak bu nedenle başarısız oldular.

Modelin var olup olmadığını kontrol ederek düzelttim sonra kullanın, yoksa oluşturun.

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

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

Bu benim için çalıştı. Ben değişmişti module.export = Useriçin export defaults User. Ayrıca refsdiğer modellerden Kullanıcıya ihtiyacım vardı . Değişen yüzden ben emin değilim module.exportsiçin export defaultgetirilen bu konu. Yine de, bu cevap onu düzeltti gibi görünüyor.
runios

3
kötü olmak mongoose.modelsyok, en azından son sürümlerde
Pedro Luz

1
Aynı sorunu yaşadım ancak tüm testlerden önce tüm modelleri temizleyerek düzelttim:for (let model in mongoose.models) delete mongoose.models[model]
E. Sundin

Test betiğim şöyle görünüyor: "test": "NODE_ENV=test mocha --file mocha.config.js --watch"ve bu config js dosyasında, kurulum ve sökümü işlemek için bir before()ve var after(). @ E.Sundin burada mükemmel çözümü sağladı ve büyüleyici bir şekilde çalışıyor. Teşekkür ederim!
Brandon Aaskov

21

Bu sorunu yaşıyorum ve şema tanımları nedeniyle değil, sunucusuz çevrimdışı moddan kaynaklanıyordu - sadece şununla çözmeyi başardım:

serverless offline --skipCacheInvalidation

Burada bahsedilmiş olan https://github.com/dherault/serverless-offline/issues/258

Umarım bu, projelerini sunucusuz ve çevrimdışı modda çalışan bir başkasına yardımcı olur.


2
Çok yararlı. Teşekkürler.
Thanh Truong

2
Önbellek geçersiz module.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);
kılmayı

günümü yaptın
fstasi

Milyonlarca kez teşekkürler!
AndyFaizan

Bu çok yardımcı oldu. Teşekkür ederim!
ifiok

20

Sunucusuz çevrimdışı kullanıyorsanız ve kullanmak istemiyorsanız --skipCacheInvalidation, aşağıdakileri çok iyi kullanabilirsiniz:

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

Bunu, bir modeli diğerinin içine aktarıyorsanız, hatta--skipCacheInvalidation
Powderham

1
Next.js'de kullanmak için aradığım tam cevap budur. Keşke bu sayfada daha yukarıda olsaydı!
Brendan Nee

18

Burada yaptıysanız, benim yaptığım sorunu yaşamış olabilirsiniz. Sorunum , aynı isimde başka bir model tanımlamamdı . Galerimi ve dosya modelimi "Dosya" olarak adlandırdım. Lanet olsun, kopyalayıp yapıştırın!


11

Bu, şöyle yazarken başıma geldi:

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

Ancak, gerçek yol "../myUser/User.js" dir.


İçe aktarırken şema yollarının karıştırılması bu soruna neden oluyor gibi görünüyor - şemayı içe aktaran tüm dosyaların aynı durumu kullandığını kontrol edin.
Andrew Cupper

bu bizi kurtardı! bunun pencereleri kullanmaktan kaynaklanabileceğini düşünüyoruz
Lyka

11

Bunu ekleyerek çözdüm

mongoose.models = {}

satırdan önce:

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

Umarım sorununuzu çözer


Yaptığım buydu ve düzeltti. mongoose.connection.models = {};
Fortune

6

Bunu çözmek için, modelin oluşturulup oluşturulmadığını kontrol edin:

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

4

Kabul edilen bir çözüm olduğunu biliyorum, ancak mevcut çözümün, Modelleri test edebilmeniz için çok sayıda standart şablonla sonuçlandığını düşünüyorum. Benim çözümüm, esasen modelinizi alıp onu bir işlevin içine yerleştirerek, Model kayıtlı değilse yeni Modeli döndürmek, ancak varsa mevcut Modeli geri vermektir.

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

Bağlantıları her yerde açmak ve kapatmak sinir bozucudur ve iyi sıkışmaz.

Bu şekilde, modele testlerimde iki farklı yerde veya daha spesifik olarak ihtiyaç duyarsam, hata almam ve tüm doğru bilgiler iade edilir.



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

Aynı problemi yaşadım, neden şema bir JS fonksiyonunda bir model tanımladım, bunlar bir fonksiyonda değil, bir düğüm modülünde global olarak tanımlanmalıydı.


1

Bu hatayı atmanın başka bir yolu var.

Modele giden yolun büyük / küçük harfe duyarlı olduğunu unutmayın.

"Kategori" modelini içeren bu benzer örnekte, hata şu koşullar altında atılmıştır:

1) Require ifadesi iki dosyada belirtilmiştir: ..category.js ve ..index.js 2) Ben birinci durum doğruydu, ikinci dosyada ise aşağıdaki gibi değildi:

category.js

görüntü açıklamasını buraya girin

index.js

görüntü açıklamasını buraya girin


0

Şema tanımı bir koleksiyon için benzersiz olmalı, bir koleksiyon için birden fazla şema olmamalıdır.


0

şema zaten olduğundan, yeni şema oluşturmadan önce doğrulayın.

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

Bunu yaparak kolayca çözebilirsiniz

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

0

Modeli her istekle dinamik olarak oluşturmam gereken bir durum var ve bu nedenle bu hatayı aldım, ancak bunu düzeltmek için kullandığım şey aşağıdaki gibi deleteModel yöntemini kullanmaktı :

var contentType = 'Product'

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

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

mongoose.deleteModel(contentType);

Umarım bu herkese yardımcı olabilir.


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

Typegoose ve Mongoose karışımı olan bir kod tabanı nedeniyle burada biten tüm insanlar için :

Her biri için bir db bağlantısı oluşturun:

Firavun faresi:

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

Typegoose:

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

0

Kopyasını yapıştırırken bir hata yapıyorum. Bir satırda, diğer modelde (Reklam modeli) aynı ada sahiptim:

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

Doğru:

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

Bu arada, birisi "otomatik kaydetme" özelliğine sahipse ve aşağıdaki gibi sorgular için dizin kullanıyorsa:

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

Dizini silmeli ve doğru model için yeniden yazmalıdır:

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

0

Bunu yaparak bu sorunu çözdüm

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

const Schema = mongoose.Schema;

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

Sonra diğer dosyalarda

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

Daha İyi Çözüm

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

Umarım bu yardımcı olur...


Açıklama sağlamanın neden bu kadar zor olduğuna dair hiçbir ipucu yok. Herkes kodunuzu okurken harcadığınız zamanı hayal edin.
robertfoenix

-1

Bu sorun gerçekleştiğinden beri, modeli başka bir zaman aramaktan. Model kodunuzu try catch bloğuna kaydırarak bu soruna geçici bir çözüm bulun. typcript kodu böyledir -

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

Benzer şekilde js'de de kod yazabilirsiniz.


-2

Check.js ve insert.js'de aynı değişken adı "user" olan mongoose.model kullanıyorsunuz.


-4

Expressjs ile çalışıyorsanız, model tanımınızı app.get () dışına taşımanız gerekebilir, böylece komut dosyası başlatıldığında yalnızca bir kez çağrılır.


bu mantıklı değil, firavun faresi modelleri, adlandırma ile ilgili bir sorun olmadıkça (örneğin, vaka) yalnızca bir kez tanımlanır, ilk çağrıldığında başlatıldığında, gelecek yalnızca örneği almalı ve onu yeniden başlatmamalı
jonnie

Bu bir çözüm değil.
Prathamesh More
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.