2014-11-09 95 views
7

我很頭痛,嘗試通過模塊將一些常見模式定義分享給我的代碼庫中的所有其他模塊。外部模塊中的模式在Node.js中不起作用

我有一個包含這兩種模式一個myproj_schemas模塊:

var mongoose = require('mongoose'), 
    util = require("util"), 
    Schema = mongoose.Schema; 

var BaseProfileSchema = function() { 
    Schema.apply(this, arguments); 

    this.add({ 
     _user: {type: Schema.Types.ObjectId, ref: 'User', required: true}, 
     name: {type: String, required: true}, 
     bio: {type: String, required: true}, 
     pictureLink: String 
    }); 

}; 
util.inherits(BaseProfileSchema, Schema); 

module.exports = BaseProfileSchema; 

而且

var mongoose = require('mongoose'), 
    BaseProfileSchema = require('./base_profile_schema.js'), 
    Schema = mongoose.Schema; 

var entSchemaAdditions = { 
    mentors: {type: Schema.Types.ObjectId, ref: 'Mentor'} 
}; 


var entrepreneurSchema = new BaseProfileSchema(entSchemaAdditions); 

module.exports = entrepreneurSchema; 

導師也是在另一個文件中定義。

我的單元測試這兩個工作在schemas模塊。

當我NPM安裝該模塊並嘗試使用

Entrepreneur = db.model('Entrepreneur', entrepreneurSchema), 

我收到以下錯誤創建:

類型錯誤:未定義類型在paths.mentors 你嘗試築巢的架構?您只能使用參考或數組進行嵌套。

如果我在本地模塊中使用相同的代碼,那麼沒問題。 如果我在require中直接引用模式文件(例如require('../ node_modules/myproj_schemas/models/ent_schema'),那麼我會得到錯誤信息。

我確信它不會像這樣破壞較早,但我已經備份了所有的變化,它仍然沒有工作

我畫一個完整的空白,並且任何建議將受到歡迎

編輯:。

我已經創建了一個新的Schemas模塊,它有一個Schema:

var mongoose = require('mongoose'); 

var userSchema = new mongoose.Schema({ 
    email: String 
}); 

module.exports = userSchema; 

當打包到模塊中並將npm安裝到其他模塊時,這也會失敗。

運行在OS X

回答

6

個人而言,我創建了單獨的「共同」項目與init方法進行登記的所有車型的共同模式的貓鼬插件mongodb,然後在任何需要訪問模型的應用程序的app.js文件中調用init方法。

  1. 創建共享項目 - 按照標​​準過程創建新節點項目。
  2. 的package.json - 在共享項目中,設置您的package.json文件包含以下項:

    "main": "index.js" 
    
  3. 添加模型 - 共享項目中創建一個新的文件夾models,以包含你所有的貓鼬模式和插件。將您的userSchema文件添加到模型文件夾並將其命名爲user.js

    var mongoose = require('mongoose'); 
    
    var userSchema = new mongoose.Schema({ 
        email: String 
    }); 
    
    module.exports = mongoose.model('User', userSchema); 
    
  4. index.js - 然後在項目的根index.js文件創建可由您的應用程序一起使用,露出模型和init方法的共享對象。有許多方法來編寫這一點,但這裏是我如何做它:

    function Common() { 
        //empty array to hold mongoose Schemas 
        this.models = {}; 
    } 
    
    Common.prototype.init = function(mongoose) { 
        mongoose.connect('your mongodb connection string goes here'); 
        require('./models/user'); 
        //add more model references here 
    
        //This is just to make referencing the models easier within your apps, so you don't have to use strings. The model name you use here must match the name you used in the schema file 
        this.models = { 
         user: mongoose.model('User') 
        } 
    } 
    
    var common = new Common(); 
    
    module.exports = common; 
    
  5. 參考您的common項目 - 但是要引用您的共享項目中,引用添加到共享項目中package.json文件在您的應用程序中,並給它一個名稱common。我個人使用GitHub來存儲項目並引用存儲庫路徑。由於我的存儲庫是私有的,我必須在GitHub支持站點上覆蓋的路徑中使用一個密鑰。
  6. 初始化在您的應用程序模型 - 在你的應用程序的啓動腳本(假設它是app.js在這個例子中)的引用添加到您的common項目,並調用init方法連接到MongoDB服務器和註冊楷模。

    //at the top, near your other module dependencies 
    var mongoose = require('mongoose') 
        , common = require('common'); 
    
    common.init(mongoose); 
    
  7. 使用模型中的任何地方你的應用程序 - 現在,貓鼬已經建立了連接池和模型已經被註冊,您可以使用這些模型是任何你的應用程序中的類的。例如,假設你有一個顯示有關user的信息,你可以做這樣一個網頁(未經測試的代碼,就寫了這個爲例):

    var common = require('common'); 
    
    app.get('/user-profile/:id', function(req, res) { 
        common.models.user.findById(req.params.id, function(err, user) { 
         if (err) 
          console.log(err.message); //do something else to handle the error 
         else 
          res.render('user-profile', {model: {user: user}}); 
        }); 
    }); 
    

編輯 對不起,我沒看不到你從另一個模式繼承一個模式的行。作爲其他答案之一,貓鼬已經提供了plugin的概念。在你上面的例子,你可以這樣做:

在您的通用模塊,在「/models/base-profile-plugin.js」

module.exports = exports = function baseProfilePlugin(schema, options){ 

    //These paths will be added to any schema that uses this plugin 
    schema.add({ 
     _user: {type: Schema.Types.ObjectId, ref: 'User', required: true}, 
     name: {type: String, required: true}, 
     bio: {type: String, required: true}, 
     pictureLink: String 
    }); 

    //you can also add static or instance methods or shared getter/setter handling logic here. See the plugin documentation on the mongoose website. 
} 

在您的通用模塊,在「/型號/企業家.js文件

var mongoose = require('mongoose') 
    , basePlugin = require('./base-profile-plugin.js'); 

var entrepreneurSchema = new mongoose.Schema({ 
    mentors: {type: Schema.Types.ObjectId, ref: 'Mentor'} 
}); 

entrepreneurSchema.plugin(basePlugin); 

module.exports = mongoose.model('Entrepreneur', entrepreneurSchema); 
+0

感謝這樣一個完整的答案。由於有這個問題,我更多地轉向這種類型的解決方案,它不需要我在模塊之間共享模式。我仍然不清楚爲什麼會出現問題,但我開始認爲這是環境問題,也許一些緩存清理會有所幫助。 – JonRed 2014-11-20 17:37:25

+0

我打算接受這個答案 - 並不是因爲它直接回答我的問題,而是因爲我認爲它將最高級別服務於社區。再次感謝您的努力。 – JonRed 2014-11-20 17:38:16

+0

我沒有真正得到這個工作,並且不得不使用'proxyquire'來覆蓋我的模式定義模塊中使用的Mongoose實例。工程,但似乎很骯髒。 – Mikke 2015-01-28 10:59:01

1

你基本上找的是對模式的繼承,有一個叫貓鼬伸出,實際上解決您的問題的項目,你可以決定是否要實現它還是去看一下代碼,做你自己的。

剛剛安裝USNG NPM

$ npm install mongoose-schema-extend 

這是它如何工作的:

var mongoose = require('mongoose'), 
    extend = require('mongoose-schema-extend'); 
var Schema = mongoose.Schema; 

var PersonSchema = new Schema({ 
    name : String 
}, { collection : 'users' }); 

var EmployeeSchema = PersonSchema.extend({ 
    department : String 
}); 

var Person = mongoose.model('Person', PersonSchema), 
    Employee = mongoose.model('Employee', EmployeeSchema); 

var Brian = new Employee({ 
    name : 'Brian Kirchoff', 
    department : 'Engineering' 
}); 

問候

+0

這是一個非常有用的答案,但沒有解決問題。在編輯中,您可以看到我遇到了非擴展架構的問題。我越來越確信,這個問題是環境問題,但沒有機會在另一臺機器上證明它。 – JonRed 2014-11-20 17:32:57