From 1ec3d67d14f6837cfb9fd7c8a4f7bd2ad3621a0d Mon Sep 17 00:00:00 2001 From: Joshua Thomas Date: Wed, 23 Sep 2015 07:58:24 -0700 Subject: [PATCH] issue #85 - findByUser now goes to ES --- lib/data/postings.js | 134 ++++++++++++++++++++++++++++++++--------- lib/models/postings.js | 16 +++++ lib/routes/users.js | 6 +- 3 files changed, 126 insertions(+), 30 deletions(-) diff --git a/lib/data/postings.js b/lib/data/postings.js index f3f5e1d..02a5d8f 100644 --- a/lib/data/postings.js +++ b/lib/data/postings.js @@ -509,46 +509,122 @@ module.exports = function (app, es, self) { self.findByUsername = function (username, options, callback) { var - query = { username : username }, + query = { + query : { + filtered : { + query : { + term : { + username : username + } + } + } + } + }, + result = { + options : options, + results : [], + total : 0 + }, verr; - // check to see if questions should be limited to those with answers - if (options.excludeEmptyQuestions) { - query.questions = query.questions || {}; - - query.questions.$not = { - $size : 0 - }; - - delete options.excludeEmptyQuestions; - } - // check to see if a date based query is necessary if (options.from) { - query.questions = query.questions || {}; - - query.questions.$elemMatch = { - createdAt : { - $gte : new Date(options.from) + query.query.filtered.filter = { + range : { + createdAt : { + from : new Date(options.from) + } } }; delete options.from; } - Posting - .find(query) - .lean() // ensures Mongoose methods are stripped off - .filter(options) - .order(options) - .page(options, function (err, postings) { - if (err) { - verr = new VError( - err, - 'unable to find postings for username %s', - username); + async.waterfall([ + // go to Elasticsearch for first layer of search + function (next) { + return es.search({ + _type : DEFAULT_POSTING_TYPE, + from : options.start, + size : options.count + }, + query, + function (err, data) { + if (err) { + verr = new VError( + err, + 'unable to find postings for username %s', + username); - return callback(verr); + verr.query = query; + verr.options = options; + + return next(verr); + } + + // return... + return next(null, data.hits); + }); + }, + + // now further filter in MongoDB + function (hits, next) { + if (hits) { + var postingIds = []; + + hits.hits.forEach(function (hit) { + postingIds.push(hit._id); + }); + + query = { + postingId : { + $in : postingIds + } + }; + + app.log.trace( + 'filtered to %d postings via Elasticsearch', + postingIds.length); + } + + // second layer of filtering + Posting + .find(query) + .lean() + .exec(function (err, postings) { + if (err) { + verr = new VError(err, 'unable to find posting details'); + + return next(verr); + } + + var + result = { + options : options, + results : [], + total : hits.total + }, + resultHash = {}; + + // sort the results in order of results from Elasticsearch + postings.forEach(function (posting) { + resultHash[posting.postingId] = posting; + }); + + hits.hits.forEach(function (hit) { + var posting = resultHash[hit._id]; + + if (posting) { + result.results.push(posting); + } + }); + + return next(null, result); + }); + } + ], function (err, postings) { + if (err) { + return callback(err); } return callback(null, extensions.transformPageResults(postings)); diff --git a/lib/models/postings.js b/lib/models/postings.js index 072a13d..f6410b8 100644 --- a/lib/models/postings.js +++ b/lib/models/postings.js @@ -806,6 +806,22 @@ module.exports = function (app, data, services, self) { return setImmediate(callback, modelError); } + if (validation.isEmpty(options.count)) { + options.count = DEFAULT_EXPANSION_COUNT; + } else { + options.count = + parseInt(expansions.count, 10) || + DEFAULT_EXPANSION_COUNT; + } + + if (validation.isEmpty(options.start)) { + options.start = 0; + } else { + options.start = + parseInt(options.start, 10) || + 0; + } + data.postings.findByUsername(username, options, function (err, postings) { if (err) { modelError = new errors.PersistenceError( diff --git a/lib/routes/users.js b/lib/routes/users.js index 872d8e9..762aebf 100644 --- a/lib/routes/users.js +++ b/lib/routes/users.js @@ -60,7 +60,11 @@ module.exports = function (app, models, self) { router.get('/:username/postings', function (req, res, next) { models.postings.findByUsername( req.params.username, - req.queryOptions, + { + count : req.query.count, + from : req.query.from, + start : req.query.start + }, function (err, postings) { if (err) { return next(err);