不能将 $match 与 mongoose 和聚合框架一起使用
Posted
技术标签:
【中文标题】不能将 $match 与 mongoose 和聚合框架一起使用【英文标题】:Can't use $match with mongoose and the aggregation framework 【发布时间】:2013-01-11 03:54:42 【问题描述】:这是我的架构:
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
查询,我得到了图像,但我得到了所有的图像,而不仅仅是我关注的用户的图像。
有什么解决办法吗...?
感谢您的提前!
编辑:
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'
【问题讨论】:
你有user
在unwind之前投影出来,如果你打算在unwind之后使用,编辑:读得太快,你必须把_id
投影出去
如何将_id
投射出去?
【参考方案1】:
Mongoose 不会对aggregate
的参数进行任何基于模式的转换,因此您需要将user.follow
字符串ID 数组转换为$match
中的ObjectId 数组:
$match: _id:
$in: user.follow.map(function(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); )
,
$project: imagen: true,
$unwind: '$imagen',
$sort: 'imagen.date': 1,
function (err, images) ...
【讨论】:
仍然返回未定义。我需要做更多的事情吗? @MrMangado 您能否编辑您的问题以包含一两个示例文档?您越容易让人们重现您的问题,就越容易完全回答。 更新。我希望它会有所帮助 @MrMangado 谢谢,但我希望您也可以包含一个示例usermodel
文档。
注意:ObjectId 构造函数存在于两个地方:mongoose.Types.ObjectId
和 mongoose.Schema.Types.ObjectId
。后者对我不起作用!希望对某人有所帮助。【参考方案2】:
对于偶然发现这个问题的任何人,希望有一个更“通用”的解决方案,需要手动 .map
或手动进行转换/转换,这里有一个 may
为您工作的解决方案:
要求:$match 的查询对象必须适合您创建的某些架构。
一般解决方案:
Model.aggregate([
$match: Model.where(yourQueryObject).cast(QueryModel);
]);
这里的问题是 Mongoose Query API 的 Query#cast
,它可以帮助您将普通对象转换为架构定义的任何内容。这有助于规范化 ObjectID、字符串和数字。
此问题的可能解决方案:
仅考虑 $match 阶段:
$match: usermodel.where(_id: $in: user.follow ).cast(usermodel)
【讨论】:
以上是关于不能将 $match 与 mongoose 和聚合框架一起使用的主要内容,如果未能解决你的问题,请参考以下文章
修改对象中的日期以在 mongoose 中进行聚合 $match 查询