Merge branch 'master' into 217-ckan-backend
This commit is contained in:
@@ -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: [
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user