Aggregating UserCodeProblems by level with an index instead of aggregating all ever

This commit is contained in:
Nick Winter 2015-11-14 16:34:35 -08:00
parent 3562b50bc0
commit 9624885fe2
2 changed files with 6 additions and 31 deletions

View file

@ -8,4 +8,6 @@ UserCodeProblemSchema = new mongoose.Schema({
'default': Date.now 'default': Date.now
}, {strict: false,read:config.mongo.readpref}) }, {strict: false,read:config.mongo.readpref})
UserCodeProblemSchema.index {levelID: 1, _id: 1}, {name: 'user code problems by level and date index'}
module.exports = UserCodeProblem = mongoose.model('user.code.problem', UserCodeProblemSchema) module.exports = UserCodeProblem = mongoose.model('user.code.problem', UserCodeProblemSchema)

View file

@ -47,45 +47,18 @@ class UserCodeProblemHandler extends Handler
return @sendSuccess res, [] unless levelSlug? return @sendSuccess res, [] unless levelSlug?
# Cache results for 1 day
@commonLevelProblemsCache ?= {}
@commonLevelProblemsCachedSince ?= new Date()
if (new Date()) - @commonLevelProblemsCachedSince > 86400 * 1000 # Dumb cache expiration
@commonLevelProblemsCache = {}
@commonLevelProblemsCachedSince = new Date()
cacheKey = levelSlug
cacheKey += 's' + startDay if startDay?
cacheKey += 'e' + endDay if endDay?
return @sendSuccess res, commonProblems if commonProblems = @commonLevelProblemsCache[cacheKey]
# Build query # Build query
match = if startDay? or endDay? then {$match: {$and: []}} else {$match: {}} match = if startDay? or endDay? then {$match: {$and: [levelID: levelSlug]}} else {$match: {levelID: levelSlug}}
match["$match"]["$and"].push _id: {$gte: utils.objectIdFromTimestamp(startDay + "T00:00:00.000Z")} if startDay? match["$match"]["$and"].push _id: {$gte: utils.objectIdFromTimestamp(startDay + "T00:00:00.000Z")} if startDay?
match["$match"]["$and"].push _id: {$lt: utils.objectIdFromTimestamp(endDay + "T00:00:00.000Z")} if endDay? match["$match"]["$and"].push _id: {$lt: utils.objectIdFromTimestamp(endDay + "T00:00:00.000Z")} if endDay?
group = {"$group": {"_id": {"errMessage": "$errMessageNoLineInfo", "errHint": "$errHint", "language": "$language", "levelID": "$levelID"}, "count": {"$sum": 1}}} group = {"$group": {"_id": {"errMessage": "$errMessageNoLineInfo", "errHint": "$errHint", "language": "$language", "levelID": "$levelID"}, "count": {"$sum": 1}}}
sort = { $sort : { "_id.levelID": 1, count : -1, "_id.language": 1 } } sort = { $sort : { "_id.levelID": 1, count : -1, "_id.language": 1 } }
query = UserCodeProblem.aggregate match, group, sort query = UserCodeProblem.aggregate match, group, sort
query.cache()
query.exec (err, data) => query.exec (err, data) =>
if err? then return @sendDatabaseError res, err if err? then return @sendDatabaseError res, err
formatted = ({language: item._id.language, message: item._id.errMessage, hint: item._id.errHint, count: item.count} for item in data)
# Build per-level common problem lists @sendSuccess res, formatted
commonProblems = {}
for item in data
levelID = item._id.levelID
commonProblems[levelID] ?= []
commonProblems[levelID].push
language: item._id.language
message: item._id.errMessage
hint: item._id.errHint
count: item.count
# Cache all the levels
for levelID of commonProblems
cacheKey = levelID
cacheKey += 's' + startDay if startDay?
cacheKey += 'e' + endDay if endDay?
@commonLevelProblemsCache[cacheKey] = commonProblems[levelID]
@sendSuccess res, commonProblems[levelSlug]
module.exports = new UserCodeProblemHandler() module.exports = new UserCodeProblemHandler()