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 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 middleware also supports pre('aggregate') and post('aggregate') hooks. You can use aggregation middleware to transform the aggregation pipeline.
The $match stage of the pipeline can be used to filter documents so that only ones meeting certain criteria move on to the next stage. In this article, we'll discuss the $match stage in more detail and provide examples that illustrate how to perform match aggregation in MongoDB.
Connecting to MongoDBMongoose requires a connection to a MongoDB database. You can require() and connect to a locally hosted database with mongoose. connect() as shown below (for the tutorial we'll instead connect to an internet-hosted database). You can get the default Connection object with mongoose.
To use $text in the $match stage, the $match stage has to be the first stage of the pipeline.
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){ ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With