0

我有猫鼬模型定义如下:

用户.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
  }
}()

基本上我正在返回一个用户模型的客户端可以使用的公共接口。IE 我的用户路线抓取模型,可以调用定义的两个公共方法,仅此而已。我这样做是为了从我的路线中抽象出我正在使用 mongodb/mongoose 的事实。我很可能会在某个时候拥有一个与 postgres 对话的用户模型,或者可能只是切换到 postgres。因此,我不想查看代码中调用猫鼬特定函数的路由方法中的位置。

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

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

但是,如果我对猫鼬模型不止一次这样做,我会收到一个错误,指出它不能被定义两次。

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

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

4

5 回答 5

5

您应该将 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。您不会遇到此类问题,并且您的代码组织得更好。

于 2014-03-31T13:34:42.800 回答
0

我也遇到过这个问题。

您可以做的是将架构定义包装在 try catch

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

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

不确定它是否是最好的方法,但它会起作用。

于 2013-06-24T18:22:47.100 回答
0

安德烈亚斯是正确的:

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.
于 2014-01-05T17:00:14.040 回答
0

我遇到了这个问题,我想我会贡献我的答案。我遇到的问题稍微复杂一些,因为我的模式中有“参考”定义。我还没有完全理解“为什么”,但基本上正在发生的事情是依赖链导致节点两次需要相同的文件。这是经过验证的,因为我得到了两次 console.log 输出。我以前的方法是简单地导出模式而不是模型,但这很烦人,因为我必须在执行开始时引导所有模型。经过一番修修补补,我确定了这个范式(使用咖啡脚本):

Mongoose = require 'mongoose'

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

module.exports = Mongoose.model 'Foo'
于 2015-01-30T22:27:01.417 回答
0

在定义 express 的 index.js 顶部的任何其他内容之前,您只需要一次 mongoose 模型:

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

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

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

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

于 2021-03-17T01:52:42.597 回答