我是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模型机制的最佳做法是什么?
由于
答案 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等常用功能库,您可以做得更好。