Reputation: 11193
I have created an app with 2 models where the match refer to a specific league. From this I wan't to make a query to get all leagues which has upcoming matches. How can I do this or should I change the structure of my models? I've tried to make a query however this returns all upcoming matches instead of leagues with upcoming matches
Models
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var leagueSchema = new Schema({
_id: Number,
name: String,
league: Number
});
var matchSchema = new Schema({
_id: Number,
league: { type: Number, ref: 'league' },
date: Date,
homeName: String,
awayName: String
});
var League = mongoose.model('leagues', leagueSchema);
var Match = mongoose.model('matches', matchSchema);
Saving data
var queryData = {'_id': matchId, 'league': leagueId, 'date': date, 'homeName': homeTeam, 'awayName': awayTeam};
Match.findOneAndUpdate({'_id': matchId}, queryData, {upsert: true}, function(err, doc){
if(err){
console.log("Something wrong when updating data!");
}
});
Query
var oneWeekAgo = new Date();
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
Match
.find({ "date": { "$gte": oneWeekAgo } })
.populate('league')
.exec(function (err, matches) {
if (err) return handleError(err);
console.log(matches);
});
Upvotes: 1
Views: 75
Reputation: 5354
I would change your models. If I were you, I would merge the two models so you will get something like this:
var leagueSchema = new Schema({
_id: Number,
name: String,
league: Number,
matches: [{
date: Date,
homeName: String,
awayName: String
}]
});
Instead of having two models, add you matches to your league schema directly. You can do this very easily when you update your document by using the $push or $addToSet property.
If you want to add the object no matter what, use $push
. If you want to add the item if it does not exist, use $addToSet
. You query with only unique items will look like this:
var objectToPush = {
homeName: 'Test',
date: ISODate('2015-12-01')
};
League.update({league: 1}, {$addToSet: {matches: objectToPush}})
.exec(function(err, update) {
// Do something
});
If you want to query for the leagues, you will need this query:
League.find({matches: {$elemMatch: {date: {$gte: oneWeekAgo}}}})
.exec(function (err, matches) {
if (err) return handleError(err);
console.log(matches);
});
This also returns matches inside your array which do not match your filter query. If you only want matches who exactly match your criteria, you will need this query:
League.aggregate([{
$unwind: '$matches'
}, {
$match: {
'matches.date': {
$gte: ISODate('2015-11-01')
}
}
}]);
The above query $unwinds
all your array objects and then matches all items seperatly.
Upvotes: 1
Reputation: 1391
You can use distinct to get all leagues refs, then do whatever you want with them :
Match.find({"date":{ "$gte": oneWeekAgo }}).distinct('league', function (err, leaguesRef) {
//
});
Or
Match.distinct('league', {"date":{ "$gte": oneWeekAgo }}, function (err, leaguesRef) {
//
});
Upvotes: 0