为MEAN应用生成mongoose DTO

时间:2015-07-05 04:22:58

标签: node.js mongodb express mongoose

我是mongoose和node的新手,我正在使用MEAN堆栈(Mongo ExpressJS AngularJS Node)构建应用程序。

我过去使用asp.net WebAPI构建了很多API,我找不到任何关于DTO或View Models使用的文档,以减少我之间来回传输的JSON量服务器和我的前端。

我的申请是关于用户在线填写的调查。然后,每个答案用于由用户产生分数。

我的模特:

var UserSchema = new Schema({
    email: {type: String, trim: true,default: '', match: [/.+\@.+\..+/,'']},
    status: {type: String},
    token:{type: String, default: crypto.randomBytes(64).toString('hex')},
    score: {
        managementExperience: {type: Number},
        managementSkills: {type: Number},
        relevantKnowledge: {type: Number},
        commitment: {type: Number},
        acceptanceOfChange: {type: Number},
        age: {type: Number},
        totalScore: {type: Number}
    },
    answers: [
        {
            optionId: {type: Schema.Types.ObjectId}
        }
    ]
});

var SurveySchema = new Schema({
    client_id:{type: Schema.Types.ObjectId, ref: 'Client' },
    creationDate:{type: Date,default: Date.now},
    title: {type: String, trim: true},
    surveyVersion: { type: Schema.Types.ObjectId, ref: 'SurveyVersion' },
    users:[UserSchema]
});

调查屏幕本身有效,但在制作结果仪表板时,我想发送一个DTO而不是整个SurveySchema,就像这个型号一样:

var SurveySchemaLight = new Schema({
    client_id:{type: Schema.Types.ObjectId, ref: 'Client' },
    creationDate:{type: Date,default: Date.now},
    title: {type: String, trim: true},
    users:[{
        email: {type: String, trim: true,default: '', match: [/.+\@.+\..+/,'']},
        status: {type: String}
    }]
});

在.Net世界中,我希望这个模型有一个构造函数,它将SurveySchema的一个实例作为参数,但我找不到让它工作的方法。

我还尝试将两个模式链接到mongodb中的同一个集合:

mongoose.model('Survey', SurveySchema);
mongoose.model('SurveyLight', SurveySchemaLight, 'surveys');

但是当我在SurveyLight架构上运行以下查询时,我仍然会收到Survey返回的所有字段:

SurveyLight.find({'client_id': req.params.clientID}).exec(function(err, surveyList){
        res.json(surveyList);
    });

在我的堆栈中使用DTO / View模型机制的最佳做法是什么?

由于

2 个答案:

答案 0 :(得分:4)

对于" mongoose"和一般的MongoDB查询,你只是"项目"您在输出中需要的字段,忽略您不想要的其他字段。

作为一个自包含的例子:

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

var childSchema = new Schema({
  "longName": String,
  "email": String,
  "status": String
})

var parentSchema = new Schema({
  "name": String,
  "longDescription": String,
  "children": [childSchema]
})

mongoose.connect('mongodb://localhost/test');

var Parent = mongoose.model( 'Parent', parentSchema );

async.waterfall(
  [
    // remove any samples
    function(callback) {
      Parent.remove({},function(err,res) {
        callback(err)
      });
    },

    // insert some test data
    function(callback) {
      Parent.create(
        {
          "name": "Bill",
          "longDescription": "Something we don't want to see",
          "children": [
            { "longName": "don't want", "email": "a@example.com", "status": "A" },
            { "longName": "don't want", "email": "b@example.com", "status": "B" }
          ]
        },
        function(err,doc) {
          console.log( doc );
          callback(err,doc);
        }
      )
    },

    // Fetch just the fields we want
    function(doc,callback) {
      Parent.find({},"name children.email children.status", callback);
    }
  ],

  // Ouput results
  function(err,result) {
    if (err) throw err;
    console.log(result);
    process.exit();
  }
);

以下表格中的哪些输出:

// The original form of the documents
{ __v: 0,
  name: 'Bill',
  longDescription: 'Something we don\'t want to see',
  _id: 5598b6bad439a31807bfe746,
  children:
   [ { longName: 'don\'t want',
       email: 'a@example.com',
       status: 'A',
       _id: 5598b6bad439a31807bfe748 },
     { longName: 'don\'t want',
       email: 'b@example.com',
       status: 'B',
       _id: 5598b6bad439a31807bfe747 } ] }

// The output document with just selected fields
[ { _id: 5598b6bad439a31807bfe746,
    name: 'Bill',
    children:
     [ { email: 'a@example.com', status: 'A' },
       { email: 'b@example.com', status: 'B' } ] } ]

如果你想"排除"字段而不是全部明确地命名,然后在

中加上-的前缀
"-longName -children.logDescription"

但你不能"混合"这两个术语,"-_id"

除外

答案 1 :(得分:2)

在JavaScript世界中,您应该尝试从功能编程的角度来解决这个问题。您有一些数据,您想要返回此数据的子集。您不需要单独的模型定义,只需要一个地图/过滤器功能。

e.g。

SurveyLight.find({'client_id': req.params.clientID}).exec(function(err, surveyList){
        var parsedSurveyList = surveyList.map(function(survey){
          survey.users = survey.users.map(function(user){
            return {email: user.email, status: user.status};
          });
          return survey;  
        });
        res.json(parsedSurveyList);
    });

通过使用lodash等常用功能库,您可以做得更好。