diff --git a/demos/multiview/app.js b/demos/multiview/app.js index b9f99442..3bfc12a1 100755 --- a/demos/multiview/app.js +++ b/demos/multiview/app.js @@ -19,7 +19,13 @@ jQuery(function($) { } var dataset = null; if (state.dataset || state.url) { - dataset = recline.Model.Dataset.restore(state); + var datasetInfo = _.extend({ + url: state.url, + backend: state.backend + }, + state.dataset + ); + dataset = new recline.Model.Dataset(datasetInfo); } else { var dataset = new recline.Model.Dataset({ records: [ diff --git a/docs/models.markdown b/docs/models.markdown index cdef8e8f..6f2b42b1 100644 --- a/docs/models.markdown +++ b/docs/models.markdown @@ -16,10 +16,9 @@ Records. Additionally, there is a a Field object for describing the columns of a Dataset, a Query object for describing queries, and a Facet object for holding summary information about a Field (or multiple Fields). -# Models - All the models are Backbone models, that is they extend Backbone.Model. Note, -however that they do not 'sync' (load/save) like normal Backbone models. +however, that they do not 'sync' (load/save) like normal Backbone models. +

Dataset

@@ -92,8 +91,7 @@ var field = new Field({ label: 'My Field Name', // (optional: defaults to string) the type of the data in this field. - // Should be a string as per type names defined by ElasticSearch - see - // Types list on + // For list of type names see below type: 'string', // (optional - defaults to null) used to indicate how the data should be @@ -105,6 +103,21 @@ var field = new Field({ is_derived: false {% endhighlight %} +#### Types + +Types are based on the [type set of elasticsearch][types-1] with a few minor additions and modifications: + +[types-1]: http://www.elasticsearch.org/guide/reference/mapping/ + +* string +* integer (long) +* float (double) +* boolean +* geo_point +* geojson +* array +* object + #### Rendering, types and formats One can customize the rendering of fields in the user interface and elsewhere @@ -180,7 +193,7 @@ Query object has the following key attributes: * size (=limit): number of results to return * from (=offset): offset into result set - http://www.elasticsearch.org/guide/reference/api/search/from-size.html - * sort: sort order - + * sort: sort order - see below * query: Query in ES Query DSL * filter: See filters and Filtered Query * fields: set of fields to return - http://www.elasticsearch.org/guide/reference/api/search/fields.html @@ -199,6 +212,24 @@ Additions: * filters: array of ElasticSearch filters. These will be and-ed together for execution. +#### Sort + +Sort structure is inspired by but with some standardization. + +Sort structure must be as follows: + + "sort" : [ + { field: "post_date", "order" : "desc"}, + { field: "user" }, + { "name" : "desc" }, + { "age" : "desc" }, + {"_score": null} + ] + +If order is omitted it is assumed to be "desc" except in the case of _score. +_score is a special case which is used for match score if that is supported by +the backend. + #### Examples
diff --git a/src/backend.elasticsearch.js b/src/backend.elasticsearch.js
index 16a66570..1c01c534 100644
--- a/src/backend.elasticsearch.js
+++ b/src/backend.elasticsearch.js
@@ -119,6 +119,19 @@ this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
       return out;
     },
 
+    // convert from Recline sort structure to ES form
+    // http://www.elasticsearch.org/guide/reference/api/search/sort.html
+    this._normalizeSort = function(sort) {
+      var out = _.map(sort, function(sortObj) {
+        var _tmp = {};
+        var _tmp2 = _.clone(sortObj);
+        delete _tmp2['field'];
+        _tmp[sortObj.field] = _tmp2;
+        return _tmp;
+      });
+      return out;
+    },
+
     this._convertFilter = function(filter) {
       var out = {};
       out[filter.type] = {}
@@ -137,10 +150,12 @@ this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
     // @return deferred supporting promise API
     this.query = function(queryObj) {
       var esQuery = (queryObj && queryObj.toJSON) ? queryObj.toJSON() : _.extend({}, queryObj);
-      var queryNormalized = this._normalizeQuery(queryObj);
+      esQuery.query = this._normalizeQuery(queryObj);
       delete esQuery.q;
       delete esQuery.filters;
-      esQuery.query = queryNormalized;
+      if (esQuery.sort && esQuery.sort.length > 0) {
+        esQuery.sort = this._normalizeSort(esQuery.sort);
+      }
       var data = {source: JSON.stringify(esQuery)};
       var url = this.endpoint + '/_search';
       var jqxhr = makeRequest({
diff --git a/src/backend.memory.js b/src/backend.memory.js
index fe68a865..fd7f6119 100644
--- a/src/backend.memory.js
+++ b/src/backend.memory.js
@@ -67,14 +67,15 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
       results = this._applyFilters(results, queryObj);
       results = this._applyFreeTextQuery(results, queryObj);
 
-      // not complete sorting!
+      // TODO: this is not complete sorting!
+      // What's wrong is we sort on the *last* entry in the sort list if there are multiple sort criteria
       _.each(queryObj.sort, function(sortObj) {
-        var fieldName = _.keys(sortObj)[0];
+        var fieldName = sortObj.field;
         results = _.sortBy(results, function(doc) {
           var _out = doc[fieldName];
           return _out;
         });
-        if (sortObj[fieldName].order == 'desc') {
+        if (sortObj.order == 'desc') {
           results.reverse();
         }
       });
diff --git a/src/view.slickgrid.js b/src/view.slickgrid.js
index dc31ef75..f960d36c 100644
--- a/src/view.slickgrid.js
+++ b/src/view.slickgrid.js
@@ -119,15 +119,17 @@ my.SlickGrid = Backbone.View.extend({
     // Column sorting
     var sortInfo = this.model.queryState.get('sort');
     if (sortInfo){
-      var column = _.keys(sortInfo[0])[0];
-      var sortAsc = !(sortInfo[0][column].order == 'desc');
+      var column = sortInfo[0].field;
+      var sortAsc = !(sortInfo[0].order == 'desc');
       this.grid.setSortColumn(column, sortAsc);
     }
 
     this.grid.onSort.subscribe(function(e, args){
       var order = (args.sortAsc) ? 'asc':'desc';
-      var sort = [{}];
-      sort[0][args.sortCol.field] = {order: order};
+      var sort = [{
+        field: args.sortCol.field,
+        order: order
+      }];
       self.model.query({sort: sort});
     });
 
diff --git a/test/backend.memory.test.js b/test/backend.memory.test.js
index 1df9d06f..23bea1d9 100644
--- a/test/backend.memory.test.js
+++ b/test/backend.memory.test.js
@@ -40,7 +40,7 @@ test('query sort', function () {
   var data = _wrapData();
   var queryObj = {
     sort: [
-      {'y': {order: 'desc'}}
+      {field: 'y', order: 'desc'}
     ]
   };
   data.query(queryObj).then(function(out) {
@@ -49,7 +49,7 @@ test('query sort', function () {
 
   var queryObj = {
     sort: [
-      {'country': {order: 'desc'}}
+      {field: 'country', order: 'desc'}
     ]
   };
   data.query(queryObj).then(function(out) {
@@ -58,7 +58,7 @@ test('query sort', function () {
 
   var queryObj = {
     sort: [
-      {'country': {order: 'asc'}}
+      {field: 'country', order: 'asc'}
     ]
   };
   data.query(queryObj).then(function(out) {
@@ -216,7 +216,7 @@ test('query sort', function () {
   var data = dataset._store.data;
   var queryObj = {
     sort: [
-      {'y': {order: 'desc'}}
+      {field: 'y', order: 'desc'}
     ]
   };
   dataset.query(queryObj).then(function() {