不止一次在mongoose模型上调用require

时间:2013-06-24 14:15:04

标签: node.js mongoose

我的mongoose模型定义如下:

user.js的

module.exports = function() {
  var mongoose = require('mongoose');

  // Creates a new Mongoose Schema object
  var Schema = mongoose.Schema; 

  // Collection to hold users
  var UserSchema = new Schema({
      username: { type: String, required: true },
      password: { type: String, required: true },
    },{ 
      versionKey: false 
    }
  );

  // Creates the Model for the User Schema
  var User = mongoose.model('User', UserSchema);

  var getUserById = function(id, callback) {
    User.findById(id, callback);
  }

  var getUserByUsername = function(username, callback) {
    var query = {username: username};
    User.findOne(query, callback);
  }


  return {
    getUserById: getUserById,
    getUserByUsername: getUserByUsername
  }
}()

基本上我正在返回User模型的客户端可以使用的公共接口。 I.E.我的用户路由抓取模型,可以调用定义的两个公共方法,而不是其他任何东西。我这样做是为了抽象我在路线上使用mongodb / mongoose的事实。我很可能会有一个User模型在某些时候与postgres交谈,或者可能只是切换到postgres。因此,我不想查看调用mongoose特定函数的routes方法中的位置代码。

这是我的问题。当我需要一个模块时,代码中的大多数地方都会调用

var someUtil = require('./someUtil');

但是,如果我为一个猫鼬模型多次这样做,我会收到一个错误,指出它无法定义两次。

var User = require('./user');  // Cannot put this in more than one file without getting an error.

是否有更好的方法来编写user.js文件,以便我可以为我的用户模型提供公共接口,但只定义一次Schema,以便我可以在该文件上调用多次?

5 个答案:

答案 0 :(得分:3)

你应该将Mongoose模型与你用它包装的服务分开。

我建议你有一个模型文件夹,每个模式有1个文件,每个文件看起来都像这样:

'use strict';

var mongoose = require('mongoose'),
    Schema = mongoose.Schema

var User = new Schema({
    ...fields your schema will have
})

//additional virtuals or configuration

module.exports = mongoose.model('User', User)

然后有一个services文件夹,其中UserService需要该模型:

var User = require('../models/User')

function UserService(){
    //create User, delete User, etc.
}

module.exports = new UserService()

然后从现在开始在您的控制器或路由中只需要UserService。你不会遇到这类问题而且你的代码组织得更好。

答案 1 :(得分:0)

我也遇到过这个问题。

您可以做的事情是将模式定义包装在try catch

将此行var User = mongoose.model('User', UserSchema);替换为:

var User;
try {
  User = mongoose.model('User', UserSchema);
}
catch(e) {
  User = mongoose.model('User');
}

不确定它是否是最佳方式,但它会起作用。

答案 2 :(得分:0)

Andreas是对的:

AFAIK node caches the result of requireing a module, and thus the above function should not be run twice. Other than that there's no reason to wrap you code in a self-executing function, just expose the methods like exports.getUserById = getUserById; //etc.

答案 3 :(得分:0)

我遇到了这个问题,我想我会贡献我的答案。我遇到的问题稍微复杂一点,因为我已经反对了#39;我的架构中的定义。我还没有达到"为什么"但基本上发生的事情是,依赖链导致节点需要两次相同的文件。这已经过验证,因为我得到了两次console.log输出。我之前的方法是简单地导出模式而不是模型,但这很烦人,因为我必须在执行开始时引导所有模型。经过一些修补,我决定使用这个范例(使用coffeescript):

Mongoose = require 'mongoose'

unless 'Foo' in Mongoose.modelNames()
  schema = new Mongoose.Schema
    bar: String
  Mongoose.model 'Foo', schema

module.exports = Mongoose.model 'Foo'

答案 4 :(得分:0)

在你定义 express 的 index.js 之上的其他任何东西之前,你只需要一次猫鼬模型:

require('./models/User');
const express = require('express');

然后在应用程序的其他部分,您可以按如下方式访问此模型:

const mongoose = require('mongoose');
const User = mongoose.model('User');

由于我们需要 index.js 中的模型,因此执行了这行代码:mongoose.model('User', userSchema),现在可以在应用程序的任何位置访问它