Peter Pik
Peter Pik

Reputation: 11193

Retrieve data based date mongodb

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

Answers (2)

Thomas Bormans
Thomas Bormans

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

Mateo Barahona
Mateo Barahona

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

Related Questions