Skip to content

Commit

Permalink
Merge pull request #38 from social-native/feat/add-sort-api
Browse files Browse the repository at this point in the history
Feat: add sort api
  • Loading branch information
erhathaway authored Apr 3, 2020
2 parents 546c109 + 401170a commit 679b976
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@social-native/snpkg-client-elasticsearch",
"version": "4.1.0",
"version": "4.2.0",
"description": "",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {configure} from 'mobx';
export {default as Manager} from './manager';
export {default as MappingParser} from './mapping_parser';
export {default as History} from './history';
export {default as Sort} from './sort';

export * from './history';
export * from './types';
Expand Down
26 changes: 24 additions & 2 deletions src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {decorate, observable, runInAction, reaction, toJS, computed} from 'mobx'
import Timeout from 'await-timeout';
import chunk from 'lodash.chunk';
import {PrefixSuggestion, FuzzySuggestion, BaseSuggestion} from './suggestions';
import Sort from './sort';

/**
* How the naming works:
Expand Down Expand Up @@ -138,6 +139,8 @@ class Manager<
public fieldWhiteList: string[];
public fieldBlackList: string[];

public sort: Sort;

constructor(client: IClient<ESDocSource>, options?: ManagerOptions) {
const filters =
options && options.filters
Expand Down Expand Up @@ -188,6 +191,8 @@ class Manager<
this._applyBlackAndWhiteListsToSourceParam
];

this.sort = new Sort();

this.middleware = (options && options.middleware) || DEFAULT_MANAGER_OPTIONS.middleware;
});

Expand Down Expand Up @@ -222,6 +227,17 @@ class Manager<
}
);

/**
* React to sort order changes.
* Run a new filter query.
*/
reaction(
() => JSON.stringify(this.sort.esSortOrder),
() => {
this._enqueueFilteredQueryAndAggs();
}
);

reaction(
() => this.indexFieldNamesAndTypes,
(indexFieldNamesAndTypes: Record<string, ESMappingType>) => {
Expand Down Expand Up @@ -1303,7 +1319,12 @@ class Manager<
};

public _addSortToQuery = (request: ESRequest): ESRequest => {
return {...request, sort: ['_score', '_doc']};
const esSort = this.sort.esSortOrder;
if (esSort.length > 0) {
return {...request, sort: [...esSort, '_score', '_doc']};
} else {
return {...request, sort: ['_score', '_doc']};
}
};

public _addZeroPageSizeToQuery = (request: ESRequest): ESRequest => {
Expand Down Expand Up @@ -1422,7 +1443,8 @@ decorate(Manager, {
fieldsWithFiltersAndSuggestions: computed,
fieldBlackList: observable,
fieldWhiteList: observable,
hasNextPage: computed
hasNextPage: computed,
sort: observable
});

export default Manager;
106 changes: 106 additions & 0 deletions src/sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import {decorate, observable, runInAction, computed} from 'mobx';

type ESSortOrderWithOptions = {
[fieldName: string]: Omit<FieldSorting, 'field'>;
};
type ESSortOrder = Array<string | ESSortOrderWithOptions>;

type FieldSorting = {
field: string;
order?: 'asc' | 'desc';
mode?: 'min' | 'max' | 'sum' | 'avg' | 'median';
missing?: '_last' | '_first' | string;
};
class Sort {
public sortOrder: FieldSorting[] = [];

public _move = (from: number, to: number) => {
runInAction(() => {
this.sortOrder.splice(to, 0, this.sortOrder.splice(from, 1)[0]);
});
};

public _currentPosition = (fieldName: string): number | undefined => {
const position = this.sortOrder.findIndex(({field}) => field === fieldName);
return position === -1 ? undefined : position;
};

public moveForward = (fieldName: string): void => {
const position = this._currentPosition(fieldName);
if (!position) {
throw new Error(
`Field cant be moved forward until it is added as a sortable field. Add it with the method 'addToSort'. For example: 'manager.sort.addToSort(${fieldName})'`
);
}
if (position === 0) {
return;
}
if (position > 0) {
this._move(position, position - 1);
}
};

public moveBackward = (fieldName: string): void => {
const position = this._currentPosition(fieldName);
if (!position) {
throw new Error(
`Field cant be moved backward until it is added as a sortable field. Add it with the method 'addToSort'. For example: 'manager.sort.addToSort(${fieldName})'`
);
}
if (position === 0) {
return;
} else {
this._move(position, position + 1);
}
};

public addToSort = (fieldName: string, options?: Omit<FieldSorting, 'field'>): void => {
const position = this._currentPosition(fieldName);

runInAction(() => {
if (position !== undefined) {
this.removeFromSort(fieldName);
}
this.sortOrder = [...this.sortOrder, {...options, field: fieldName}];
});
};

public removeFromSort = (fieldName: string) => {
const position = this._currentPosition(fieldName);

if (position !== undefined) {
runInAction(() => {
this.sortOrder.splice(position, 1);
});
} else {
throw new Error(
`Can't remove the field ${fieldName} from the sort order because it has yet to be added. Add the field to the sort order using the 'addToSort' method. For example: 'manager.sort.addToSort(${fieldName})'`
);
}
};

public get esSortOrder(): ESSortOrder {
return this.sortOrder.reduce((acc, fieldSortInfo) => {
const {field, ...options} = fieldSortInfo;
if (Object.keys(options || {}).length > 0) {
acc.push({[field]: options});
} else {
acc.push(field);
}
return acc;
}, [] as ESSortOrder);
}

public clear = () => {
runInAction(() => {
this.sortOrder = [];
});
};
}

decorate(Sort, {
sortOrder: observable,
esSortOrder: computed
});

export default Sort;

0 comments on commit 679b976

Please sign in to comment.