不能使用$ match与mongoose和聚合框架 [英] Can't use $match with mongoose and the aggregation framework

查看:560
本文介绍了不能使用$ match与mongoose和聚合框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的模式:

  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 ,所以您需要将 user.follow 数组的字符串ID转换为 $ match

  {$ 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 $matchto filter the result, only getting the images of the user that I'm following, but the console.log show me that the result of the aggregate 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 your user.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆