不能使用$ match与mongoose和聚合框架 [英] Can't use $match with mongoose and the aggregation framework
问题描述
这是我的模式:
var userschema = new mongoose.Schema({
user :String,
follow:[String],
imagen:[{
title:String,
date:{type:Date,default:Date.now}
}]
});
这是代码:
usermodel.findOne({user:req.session.user},function(err,user){
usermodel.aggregate({$ unwind:'$ imagen'},
{$ match:{_id:{$ in:user.follow}}},
{imagen:true},
{$ sort:{'imagen.date':1}},
函数(错误,图像){
console.log(images);
res.render('home.ejs',{
user:user,
following:images
});
});
});
跟随
包含用户的 _id
。
代码有效,除非我包含 $ match
。我使用 $ match
过滤结果,只得到我正在关注的用户的图像,但是console.log显示了$的结果c $ c> aggregate search是未定义的,但是当我不写 $ match
查询时,我得到图像,但是我获得了所有图像,不仅是我所关注的用户的图像。
有没有解决方案?
感谢先进!
编辑:
var express = require('express');
var MongoStore = require('connect-mongo')(express);
var fs = require('fs');
var mongoose = require('mongoose');
var app = express();
app.listen(9191);
var sessionStore = new MongoStore({db:'session'});
app.configure(function(){
app.use(express.bodyParser());
app.set('views',__ dirname +' / views');
app.set('view engine','ejs');
app.use(express.static(__ dirname +'/ public'));
app。使用(express.cookieParser());
app.use(express.session({
store:sessionStore,
secret:'secret'
}));
app.use(app.router);
});
var db = mongoose.createConnection('localhost','test');
var userschema = new mongoose.Schema({
user:String,
follow:[String],
imagen:[{
title:String,
date:{type:Date,default:Date.now}
}]
});
var usermodel = db.model('usermodel',userschema);
var ObjectId = require('mongoose')。Types.ObjectId;
app.get('/',middleware.noses,function(req,res){
res.render('home0.ejs');
});
app.get('/ home',middleware.yeses,function(req,res){
usermodel.findOne({user:req.session .user},function(err,user){
if(user.follow.length!= 0){
usermodel.find({_id:{$ in: user.follow}},{user:true},function(err,users){
var usernames = users.map(function(u){return u.user});
usermodel.aggregate({$ match:{_id:{$ in:user.follow.map(
function(id){return new ObjectId(id);})}}},
{$ unwind:'$ imagen'},
{imagen:true},
{$ sort:{'imagen.date':1}},
函数(err, {
console.log(images);
res.render('home.ejs',{
user:user,
following:images
});
});
});
} else {
res.render('home.ejs',{
user:user,
following:undefined
});
}
});
});
编辑:
code> [{__v:4,
_id:50fd9c7b8e6a9d087d000006,
follow:['50fd9cbd1322de627d000006','50fd9d3ce20da1dd7d000006'],
imagen:
[{title: foo',
_id:50fd9ca2bc9f163e7d000006,
日期:2013年1月21日星期一20:53:06 GMT + 0100(CET)},
{title:'foot',
_id :50fda83a3214babc88000005,
日期:2013年1月21日21:42:34 GMT + 0100(CET)}],
用户:'Mrmangado'}
pre>
解决方案Mongoose不会对
aggregate $的参数进行任何基于模式的转换c $ c>,所以您需要将
user.follow
数组的字符串ID转换为$ match $ c中的ObjectIds数组$ c>:
{$ match:{_id:{
$ in:user.follow.map (id){return new mongoose.Types.ObjectId(id);})
}}},
注意:不要使用
mongoose.Schema.Types.ObjectId
用于投射。
您还应该移动这个
$ match
到管道的开始效率。
更新
您的其他问题是您需要使用
$ project
运算符,而不是仅仅包含一个简单的{imagen:true}
对象管道。把它们放在一起,重新排序一个更有效的管道,这对我有用的数据:usermodel.aggregate(
{$ match:{_id:{
$ in:user.follow.map(function(id){return new mongoose.Types.ObjectId(id);})
}}} b $ b {$ project:{imagen:true}},
{$ unwind:'$ imagen'},
{$ sort:{'imagen.date':1}},
函数(错误,图像){...
This is my Schema:
var userschema = new mongoose.Schema({ user: String, follow: [String], imagen: [{ title: String, date: { type: Date, default: Date.now } }] });
And this is the code:
usermodel.findOne({ user: req.session.user }, function (err, user){ usermodel.aggregate({$unwind: '$imagen'}, {$match: { _id: { $in: user.follow } }}, {imagen: true}, {$sort: {'imagen.date': 1}}, function (err, images){ console.log(images); res.render('home.ejs', { user: user, following: images }); }); });
The
follow
contains users's_id
.The code works, except when I include the
$match
. I use the$match
to filter the result, only getting the images of the user that I'm following, but the console.log show me that the result of theaggregate
search is undefined, but when I don't write the$match
query, I get the images, but I obtain all the images, not only the images of the user that I'm following.Is there any solution for this...?
Thank's advance!
EDIT:
var express = require('express'); var MongoStore = require('connect-mongo')(express); var fs = require('fs'); var mongoose = require('mongoose'); var app = express(); app.listen(9191); var sessionStore = new MongoStore({db: 'session'}); app.configure(function(){ app.use(express.bodyParser()); app.set('views',__dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.static(__dirname + '/public')); app.use(express.cookieParser()); app.use(express.session({ store: sessionStore, secret: 'secret' })); app.use(app.router); }); var db = mongoose.createConnection('localhost', 'test'); var userschema = new mongoose.Schema({ user: String, follow: [String], imagen: [{ title: String, date: { type: Date, default: Date.now } }] }); var usermodel = db.model('usermodel', userschema); var ObjectId = require('mongoose').Types.ObjectId; app.get('/', middleware.noses, function (req, res){ res.render('home0.ejs'); }); app.get('/home', middleware.yeses, function (req, res){ usermodel.findOne({ user: req.session.user }, function (err, user){ if (user.follow.length != 0){ usermodel.find({ _id: {$in: user.follow } }, { user: true }, function (err, users){ var usernames = users.map(function(u){ return u.user }); usermodel.aggregate({$match: { _id: { $in: user.follow.map( function(id){ return new ObjectId(id); })}}}, {$unwind: '$imagen'}, {imagen: true}, {$sort: {'imagen.date': 1}}, function (err, images){ console.log(images); res.render('home.ejs', { user: user, following: images }); }); }); } else { res.render('home.ejs', { user: user, following: undefined }); } }); });
EDIT:
[ { __v: 4, _id: 50fd9c7b8e6a9d087d000006, follow: ['50fd9cbd1322de627d000006', '50fd9d3ce20da1dd7d000006'], imagen: [{ title: 'foo', _id: 50fd9ca2bc9f163e7d000006, date: Mon Jan 21 2013 20:53:06 GMT+0100 (CET) }, { title: 'foot', _id: 50fda83a3214babc88000005, date: Mon Jan 21 2013 21:42:34 GMT+0100 (CET) }], user: 'Mrmangado' }
解决方案Mongoose doesn't do any schema-based casting of the arguments of
aggregate
, so you need to convert youruser.follow
array of string ids into an array of ObjectIds in the$match
:{$match: { _id: { $in: user.follow.map(function(id){ return new mongoose.Types.ObjectId(id); }) }}},
NOTE: Do not use
mongoose.Schema.Types.ObjectId
for casting. It will not work.You should also move this
$match
to the beginning of the pipeline for efficiency.UPDATE
Your other problem is you need to use a
$project
operator instead of just including a plain{imagen: true}
object in the pipeline. Putting it all together and reordering for a more efficient pipeline, this worked for me with your data:usermodel.aggregate( {$match: { _id: { $in: user.follow.map(function(id){ return new mongoose.Types.ObjectId(id); }) }}}, {$project: {imagen: true}}, {$unwind: '$imagen'}, {$sort: {'imagen.date': 1}}, function (err, images){ ...
这篇关于不能使用$ match与mongoose和聚合框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!