From 1be5bdec2501e4202a0a39aac23b31836aad4cc8 Mon Sep 17 00:00:00 2001 From: Ben Reinhart Date: Mon, 16 Jun 2014 18:45:56 -0500 Subject: [PATCH] WIP --- components/search/middleware/build_query.js | 7 ++++--- components/search/middleware/index.js | 1 + components/search/middleware/parse_page.js | 15 +++++++++++++++ components/search/query.js | 11 +++++++++-- components/search/results.client.js | 5 +++-- components/search/router.client.js | 4 ++-- components/search/views/form.js | 6 +++--- components/search/views/react/form.jsx | 3 ++- core/lib/elasticsearch/query_builders.js | 7 ++++--- .../core/lib/elasticsearch/query_builders_test.js | 11 +++++++++-- 10 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 components/search/middleware/parse_page.js diff --git a/components/search/middleware/build_query.js b/components/search/middleware/build_query.js index 5e5a0ec..da13c9f 100644 --- a/components/search/middleware/build_query.js +++ b/components/search/middleware/build_query.js @@ -11,14 +11,15 @@ var toQuery = requireRoot('components/search/query'); */ exports.buildQuery = function *(next) { - var query = this.request.body.query + var body = this.request.body + , query = body.query , sort = query.sort , qualifier = query.qualifier.qualifier; - this.request.body.reverse = 'last' === qualifier + body.reverse = 'last' === qualifier ? 'asc' === sort : 'desc' === sort; - this.request.body.query = toQuery(query); + body.query = toQuery(query, body.page); yield next; } diff --git a/components/search/middleware/index.js b/components/search/middleware/index.js index 38e8447..e54bfe0 100644 --- a/components/search/middleware/index.js +++ b/components/search/middleware/index.js @@ -3,5 +3,6 @@ var compose = require('koa-compose'); module.exports = compose([ requireRoot('components/search/middleware/enforce_query').enforceQuery, requireRoot('components/search/middleware/parse_query').parseQuery, + requireRoot('components/search/middleware/parse_page').parsePage, requireRoot('components/search/middleware/build_query').buildQuery ]); diff --git a/components/search/middleware/parse_page.js b/components/search/middleware/parse_page.js new file mode 100644 index 0000000..1d0de78 --- /dev/null +++ b/components/search/middleware/parse_page.js @@ -0,0 +1,15 @@ +var number = /^\d+$/; + +/** + * Validates the request `page` param, defaults + * to 0 in the event that the param is anything but + * a valid number. Also parses the number from a + * string to a number. + */ + +exports.parsePage = function *(next) { + var page = 0, reqPage = this.request.body.page; + if (number.test(reqPage)) page = Math.abs(+reqPage); + this.request.body.page = page; + yield next; +} diff --git a/components/search/query.js b/components/search/query.js index 1e0ca25..220d8b4 100644 --- a/components/search/query.js +++ b/components/search/query.js @@ -1,10 +1,13 @@ module.exports = toQuery; +const DEFAULT_PAGE_SIZE = requireRoot('core/config').search.DEFAULT_SIZE; + var extend = require('underscore').extend , QueryBuilder = requireRoot('core/lib/elasticsearch/query_builders'); -function toQuery(search) { +function toQuery(search, page) { var at = search.at + , from = getFrom(page) , range = search.dateRange , qualifier = search.qualifier , sort = 'last' === qualifier.qualifier ? 'desc' : 'asc' @@ -12,7 +15,7 @@ function toQuery(search) { query = extend( QueryBuilder.buildSort('date', sort), - QueryBuilder.buildSize(qualifier.arguments[0]), + QueryBuilder.buildSize({size: qualifier.arguments[0], from: from}), QueryBuilder.buildFilter( QueryBuilder.buildDateRange(range.from, range.to) ) @@ -27,3 +30,7 @@ function toQuery(search) { function buildVenueQuery(at) { return QueryBuilder.buildFuzzyLikeThis(["venue.name"], at); } + +function getFrom(page) { + return page * DEFAULT_PAGE_SIZE; +} diff --git a/components/search/results.client.js b/components/search/results.client.js index 4116066..9b4b719 100644 --- a/components/search/results.client.js +++ b/components/search/results.client.js @@ -16,9 +16,10 @@ module.exports = Collection.extend({ return response.hits; }, - fetch: function(search) { + fetch: function(search, page) { + page = Math.abs(page || 0); return fetch.call(this, { - data: {query: search}, + data: {query: search, page: page}, reset: true, type: 'POST' }); diff --git a/components/search/router.client.js b/components/search/router.client.js index 9259299..2fafba2 100644 --- a/components/search/router.client.js +++ b/components/search/router.client.js @@ -18,11 +18,11 @@ module.exports = Backbone.Router.extend({ }); }, - onSearchSubmit: function(search) { + onSearchSubmit: function(search, page) { var results = new Results({model: Result}); results.on('error', this.onSearchError, this); results.on('success', this.onSearchSuccess, this); - results.fetch(search); + results.fetch(search, page); }, onSearchError: function(results, xhr) { diff --git a/components/search/views/form.js b/components/search/views/form.js index 66cbf5f..df5bfbe 100644 --- a/components/search/views/form.js +++ b/components/search/views/form.js @@ -11,11 +11,11 @@ module.exports = Backbone.View.extend({ React.renderComponent(Form({onSubmit: this.onSubmit.bind(this)}), this.$el[0]); }, - onSubmit: function(value) { - if (isEmpty(value)) + onSubmit: function(search, page) { + if (isEmpty(search)) console.log('empty'); else - this.trigger('submit', value); + this.trigger('submit', search, page); }, onError: function() { diff --git a/components/search/views/react/form.jsx b/components/search/views/react/form.jsx index a1e03e1..c1f11aa 100644 --- a/components/search/views/react/form.jsx +++ b/components/search/views/react/form.jsx @@ -4,7 +4,7 @@ module.exports = React.createClass({ handleKeyPress: function(e){ if ('Enter' !== e.key) return; e.preventDefault(); - this.props.onSubmit(e.target.value); + this.props.onSubmit(e.target.value, +$("#search-page").val()); }, render: function() { @@ -13,6 +13,7 @@ module.exports = React.createClass({ + ); } diff --git a/core/lib/elasticsearch/query_builders.js b/core/lib/elasticsearch/query_builders.js index bd72362..432e402 100644 --- a/core/lib/elasticsearch/query_builders.js +++ b/core/lib/elasticsearch/query_builders.js @@ -1,15 +1,16 @@ /** * Builds a size object * - * @param {Number} size + * @param {Object} options * @return {Object} * @api public */ -exports.buildSize = function(size) { - return {size: size}; +exports.buildSize = function(options) { + return {size: options.size, from: options.from || 0}; } + /** * Builds a filter object * diff --git a/test/core/lib/elasticsearch/query_builders_test.js b/test/core/lib/elasticsearch/query_builders_test.js index 2b48373..d135741 100644 --- a/test/core/lib/elasticsearch/query_builders_test.js +++ b/test/core/lib/elasticsearch/query_builders_test.js @@ -6,8 +6,15 @@ var expect = require('chai').expect describe('QueryBuilders', function() { describe('.buildSize', function() { it('is an elasticsearch size object', function() { - var actual = QueryBuilders.buildSize(10) - , expected = {size: 10}; + var actual = QueryBuilders.buildSize({size: 10}) + , expected = {size: 10, from: 0}; + + expect(actual).to.eql(expected); + }); + + it('is an elasticsearch size object with an explicit `from`', function() { + var actual = QueryBuilders.buildSize({size: 10, from: 2}) + , expected = {size: 10, from: 2}; expect(actual).to.eql(expected); });