Merge branch 'master' into 217-ckan-backend

This commit is contained in:
Rufus Pollock
2012-08-21 23:57:10 +01:00
6 changed files with 75 additions and 20 deletions

View File

@@ -19,7 +19,13 @@ jQuery(function($) {
} }
var dataset = null; var dataset = null;
if (state.dataset || state.url) { 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 { } else {
var dataset = new recline.Model.Dataset({ var dataset = new recline.Model.Dataset({
records: [ records: [

View File

@@ -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 a Dataset, a Query object for describing queries, and a Facet object for
holding summary information about a Field (or multiple Fields). holding summary information about a Field (or multiple Fields).
# Models
All the models are Backbone models, that is they extend Backbone.Model. Note, 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.
<h2 id="dataset">Dataset</h2> <h2 id="dataset">Dataset</h2>
@@ -92,8 +91,7 @@ var field = new Field({
label: 'My Field Name', label: 'My Field Name',
// (optional: defaults to string) the type of the data in this field. // (optional: defaults to string) the type of the data in this field.
// Should be a string as per type names defined by ElasticSearch - see // For list of type names see below
// Types list on <http://www.elasticsearch.org/guide/reference/mapping/>
type: 'string', type: 'string',
// (optional - defaults to null) used to indicate how the data should be // (optional - defaults to null) used to indicate how the data should be
@@ -105,6 +103,21 @@ var field = new Field({
is_derived: false is_derived: false
{% endhighlight %} {% 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 #### Rendering, types and formats
One can customize the rendering of fields in the user interface and elsewhere 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 * size (=limit): number of results to return
* from (=offset): offset into result set - http://www.elasticsearch.org/guide/reference/api/search/from-size.html * from (=offset): offset into result set - http://www.elasticsearch.org/guide/reference/api/search/from-size.html
* sort: sort order - <http://www.elasticsearch.org/guide/reference/api/search/sort.html> * sort: sort order - see below
* query: Query in ES Query DSL <http://www.elasticsearch.org/guide/reference/api/search/query.html> * query: Query in ES Query DSL <http://www.elasticsearch.org/guide/reference/api/search/query.html>
* filter: See filters and <a href="http://www.elasticsearch.org/guide/reference/query-dsl/filtered-query.html">Filtered Query</a> * filter: See filters and <a href="http://www.elasticsearch.org/guide/reference/query-dsl/filtered-query.html">Filtered Query</a>
* fields: set of fields to return - http://www.elasticsearch.org/guide/reference/api/search/fields.html * 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 * filters: array of ElasticSearch filters. These will be and-ed together for
execution. execution.
#### Sort
Sort structure is inspired by <http://www.elasticsearch.org/guide/reference/api/search/sort.html> 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 #### Examples
<pre> <pre>

View File

@@ -119,6 +119,19 @@ this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
return out; 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) { this._convertFilter = function(filter) {
var out = {}; var out = {};
out[filter.type] = {} out[filter.type] = {}
@@ -137,10 +150,12 @@ this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
// @return deferred supporting promise API // @return deferred supporting promise API
this.query = function(queryObj) { this.query = function(queryObj) {
var esQuery = (queryObj && queryObj.toJSON) ? queryObj.toJSON() : _.extend({}, 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.q;
delete esQuery.filters; 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 data = {source: JSON.stringify(esQuery)};
var url = this.endpoint + '/_search'; var url = this.endpoint + '/_search';
var jqxhr = makeRequest({ var jqxhr = makeRequest({

View File

@@ -67,14 +67,15 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
results = this._applyFilters(results, queryObj); results = this._applyFilters(results, queryObj);
results = this._applyFreeTextQuery(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) { _.each(queryObj.sort, function(sortObj) {
var fieldName = _.keys(sortObj)[0]; var fieldName = sortObj.field;
results = _.sortBy(results, function(doc) { results = _.sortBy(results, function(doc) {
var _out = doc[fieldName]; var _out = doc[fieldName];
return _out; return _out;
}); });
if (sortObj[fieldName].order == 'desc') { if (sortObj.order == 'desc') {
results.reverse(); results.reverse();
} }
}); });

View File

@@ -119,15 +119,17 @@ my.SlickGrid = Backbone.View.extend({
// Column sorting // Column sorting
var sortInfo = this.model.queryState.get('sort'); var sortInfo = this.model.queryState.get('sort');
if (sortInfo){ if (sortInfo){
var column = _.keys(sortInfo[0])[0]; var column = sortInfo[0].field;
var sortAsc = !(sortInfo[0][column].order == 'desc'); var sortAsc = !(sortInfo[0].order == 'desc');
this.grid.setSortColumn(column, sortAsc); this.grid.setSortColumn(column, sortAsc);
} }
this.grid.onSort.subscribe(function(e, args){ this.grid.onSort.subscribe(function(e, args){
var order = (args.sortAsc) ? 'asc':'desc'; var order = (args.sortAsc) ? 'asc':'desc';
var sort = [{}]; var sort = [{
sort[0][args.sortCol.field] = {order: order}; field: args.sortCol.field,
order: order
}];
self.model.query({sort: sort}); self.model.query({sort: sort});
}); });

View File

@@ -40,7 +40,7 @@ test('query sort', function () {
var data = _wrapData(); var data = _wrapData();
var queryObj = { var queryObj = {
sort: [ sort: [
{'y': {order: 'desc'}} {field: 'y', order: 'desc'}
] ]
}; };
data.query(queryObj).then(function(out) { data.query(queryObj).then(function(out) {
@@ -49,7 +49,7 @@ test('query sort', function () {
var queryObj = { var queryObj = {
sort: [ sort: [
{'country': {order: 'desc'}} {field: 'country', order: 'desc'}
] ]
}; };
data.query(queryObj).then(function(out) { data.query(queryObj).then(function(out) {
@@ -58,7 +58,7 @@ test('query sort', function () {
var queryObj = { var queryObj = {
sort: [ sort: [
{'country': {order: 'asc'}} {field: 'country', order: 'asc'}
] ]
}; };
data.query(queryObj).then(function(out) { data.query(queryObj).then(function(out) {
@@ -216,7 +216,7 @@ test('query sort', function () {
var data = dataset._store.data; var data = dataset._store.data;
var queryObj = { var queryObj = {
sort: [ sort: [
{'y': {order: 'desc'}} {field: 'y', order: 'desc'}
] ]
}; };
dataset.query(queryObj).then(function() { dataset.query(queryObj).then(function() {