不能将 $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}},
function (err, images){
console.log(images);
res.render('home.ejs', {
user: user,
following: images
});
});
});
follow
包含用户的 _id
.
代码有效,除非我包含 $match
.我使用 $match
来过滤结果,只获取我关注的用户的图像,但 console.log 向我显示 aggregate
的结果搜索未定义,但是当我不编写 $match
查询时,我得到了图像,但我获得了所有图像,而不仅仅是我关注的用户的图像.
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 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...?
提前谢谢!
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
});
}
});
});
[ { __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 不会对 aggregate
的参数进行任何基于模式的转换,因此您需要转换您的 user.follow
字符串 id 数组到 $match
中的 ObjectIds 数组:
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); })
}}},
注意:不要使用 mongoose.Schema.Types.ObjectId
进行转换.这行不通.
NOTE: Do not use mongoose.Schema.Types.ObjectId
for casting. It will not work.
您还应该将此 $match
移动到管道的开头以提高效率.
You should also move this $match
to the beginning of the pipeline for efficiency.
更新
您的另一个问题是您需要使用 $project
运算符,而不仅仅是在管道中包含一个普通的 {imagen: true}
对象.将所有内容放在一起并重新排序以获得更有效的管道,这对我来说对您的数据有用:
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屋!