Skip to content

Commit fef17f0

Browse files
committed
feat(SearchResolver): Add SearchResolver generated from mapping
1 parent c2b2d60 commit fef17f0

File tree

7 files changed

+139
-50
lines changed

7 files changed

+139
-50
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
},
3333
"devDependencies": {
3434
"babel-cli": "^6.24.0",
35-
"babel-eslint": "^7.1.1",
35+
"babel-eslint": "^7.2.0",
3636
"babel-plugin-transform-flow-strip-types": "^6.22.0",
3737
"babel-plugin-transform-object-rest-spread": "^6.22.0",
3838
"babel-preset-env": "^1.2.2",
@@ -48,7 +48,7 @@
4848
"express-graphql": "^0.6.3",
4949
"flow-bin": "^0.42.0",
5050
"graphql": "^0.9.1",
51-
"graphql-compose": "^1.17.3",
51+
"graphql-compose": "^1.18.0",
5252
"jest": "^19.0.2",
5353
"jest-babel": "^1.0.1",
5454
"npm-run-all": "^4.0.1",

src/elasticDSL/Commons/FieldNames.js

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ export function getAllAsFieldConfigMap(opts: mixed, fc: mixed) {
8989
return getFieldConfigMap(opts, ['_all'], fc);
9090
}
9191

92+
export function getFieldNamesByElasticType(
93+
fieldMap: any,
94+
types: ElasticDataType[]
95+
): string[] {
96+
const fieldNames = [];
97+
types.forEach(type => {
98+
if (typeof fieldMap[type] === 'object') {
99+
Object.keys(fieldMap[type]).forEach(fieldName => {
100+
fieldNames.push(fieldName);
101+
});
102+
}
103+
});
104+
return fieldNames;
105+
}
106+
92107
export function getFieldNamesType(
93108
opts: mixed,
94109
types: ElasticDataType[],
@@ -134,19 +149,15 @@ function getEnumValues(
134149
addAll: boolean = false
135150
): GraphQLEnumValueConfigMap {
136151
const values = {};
137-
types.forEach(type => {
138-
if (addAll) {
139-
values._all = {
140-
value: '_all',
141-
};
142-
}
143-
if (typeof fieldMap[type] === 'object') {
144-
Object.keys(fieldMap[type]).forEach(fieldName => {
145-
values[fieldName] = {
146-
value: fieldName.replace('__', '.'),
147-
};
148-
});
149-
}
152+
if (addAll) {
153+
values._all = {
154+
value: '_all',
155+
};
156+
}
157+
getFieldNamesByElasticType(fieldMap, types).forEach(fieldName => {
158+
values[fieldName] = {
159+
value: fieldName.replace('__', '.'),
160+
};
150161
});
151162
return values;
152163
}
@@ -175,12 +186,8 @@ export function getFieldConfigMap(
175186
// $FlowFixMe
176187
fcMap._all = fc;
177188
}
178-
types.forEach(type => {
179-
if (typeof opts.fieldMap[type] === 'object') {
180-
Object.keys(opts.fieldMap[type]).forEach(fieldName => {
181-
fcMap[fieldName] = fc;
182-
});
183-
}
189+
getFieldNamesByElasticType(opts.fieldMap, types).forEach(fieldName => {
190+
fcMap[fieldName] = fc;
184191
});
185192

186193
if (Object.keys(fcMap).length === 0) {

src/elasticDSL/SearchBody.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { InputTypeComposer } from 'graphql-compose';
44
import type { FieldsMapByElasticType } from '../mappingConverter';
55
import { getQueryITC, prepareQueryInResolve } from './Query/Query';
66
import { getAggsITC, prepareAggsInResolve } from './Aggs/Aggs';
7+
import { getSortITC } from './Sort';
78
import { getTypeName, getOrSetType, desc } from '../utils';
89

910
export type SearchOptsT = {
@@ -31,7 +32,7 @@ export function getSearchBodyITC(opts: SearchOptsT = {}): InputTypeComposer {
3132
aggs: () => getAggsITC(opts),
3233
size: 'Int',
3334
from: 'Int',
34-
sort: 'JSON',
35+
sort: () => [getSortITC(opts)],
3536
_source: 'JSON',
3637
script_fields: 'JSON',
3738
post_filter: () => getQueryITC(opts),

src/elasticDSL/Sort.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* @flow */
2+
3+
import { InputTypeComposer } from 'graphql-compose';
4+
import { GraphQLEnumType } from 'graphql';
5+
import { getTypeName, getOrSetType } from '../utils';
6+
import { getFieldNamesByElasticType } from './Commons/FieldNames';
7+
8+
const sortableTypes = [
9+
'byte',
10+
'short',
11+
'integer',
12+
'long',
13+
'double',
14+
'float',
15+
'half_float',
16+
'scaled_float',
17+
'token_count',
18+
'date',
19+
'boolean',
20+
'ip',
21+
'keyword',
22+
];
23+
24+
export function getSortITC(opts: any = {}): InputTypeComposer | string {
25+
const name = getTypeName('SortEnum', opts);
26+
const description = 'Sortable fields from mapping';
27+
28+
if (!opts.fieldMap) {
29+
return 'JSON';
30+
}
31+
32+
return getOrSetType(name, () => {
33+
const sortableFields = getFieldNamesByElasticType(
34+
opts.fieldMap,
35+
sortableTypes
36+
);
37+
if (sortableFields.length === 0) {
38+
return 'JSON';
39+
}
40+
41+
const values = {
42+
_score: {
43+
value: '_score',
44+
},
45+
};
46+
sortableFields.forEach(fieldName => {
47+
const dottedName = fieldName.replace('__', '.');
48+
values[`${fieldName}__asc`] = {
49+
value: { [dottedName]: 'asc' },
50+
};
51+
values[`${fieldName}__desc`] = {
52+
value: { [dottedName]: 'desc' },
53+
};
54+
});
55+
56+
return new GraphQLEnumType({
57+
name,
58+
description,
59+
values,
60+
});
61+
});
62+
}

src/resolvers/search.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,18 @@ export default function createSearchResolver(
8989
const bodyITC = InputTypeComposer.create(argsConfigMap.body.type);
9090
argsConfigMap.query = bodyITC.getField('query');
9191
argsConfigMap.aggs = bodyITC.getField('aggs');
92+
argsConfigMap.sort = bodyITC.getField('sort');
9293
argsConfigMap.highlight = bodyITC.getField('highlight');
9394

9495
const topLevelArgs = [
95-
'limit',
96-
'skip',
9796
'q',
98-
'opts',
9997
'query',
98+
'sort',
99+
'limit',
100+
'skip',
100101
'aggs',
101102
'highlight',
103+
'opts',
102104
];
103105
argsConfigMap.opts = InputTypeComposer.create({
104106
name: `${sourceTC.getTypeName()}Opts`,
@@ -111,14 +113,15 @@ export default function createSearchResolver(
111113
});
112114

113115
const type = getSearchOutputTC({ prefix, fieldMap, sourceTC });
116+
const hitsType = type.get('hits.hits');
114117
type
115118
.addFields({
116119
// $FlowFixMe
117120
count: 'Int',
118121
// $FlowFixMe
119122
max_score: 'Float',
120123
// $FlowFixMe
121-
hits: [type.get('hits.hits')],
124+
hits: hitsType ? [hitsType] : 'JSON',
122125
})
123126
.reorderFields([
124127
'hits',
@@ -185,6 +188,11 @@ export default function createSearchResolver(
185188
delete args.aggs;
186189
}
187190

191+
if (args.sort) {
192+
args.body.sort = args.sort;
193+
delete args.sort;
194+
}
195+
188196
if (args.opts) {
189197
args = {
190198
...args.opts,
@@ -212,7 +220,7 @@ export default function createSearchResolver(
212220

213221
return res;
214222
},
215-
}).reorderArgs(['q', 'query', 'aggs', 'limit', 'skip']);
223+
}).reorderArgs(['q', 'query', 'sort', 'limit', 'skip', 'aggs']);
216224
}
217225

218226
export function toDottedList(

src/resolvers/searchConnection.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,16 @@ export default function createSearchConnectionResolver(
1919
before: 'String',
2020
})
2121
.removeArg(['limit', 'skip'])
22-
.reorderArgs(['q', 'query', 'aggs', 'first', 'after', 'last', 'before']);
22+
.reorderArgs([
23+
'q',
24+
'query',
25+
'sort',
26+
'aggs',
27+
'first',
28+
'after',
29+
'last',
30+
'before',
31+
]);
2332

2433
const searchType = searchResolver.getTypeComposer();
2534
const typeName = searchType.getTypeName();
@@ -43,7 +52,7 @@ export default function createSearchConnectionResolver(
4352
);
4453

4554
resolver.resolve = async rp => {
46-
const { args = {} } = rp;
55+
const { args = {}, projection = {} } = rp;
4756

4857
const first = parseInt(args.first, 10) || 0;
4958
if (first < 0) {
@@ -75,9 +84,15 @@ export default function createSearchConnectionResolver(
7584
args.limit = limit + 1; // +1 document, to check next page presence
7685
args.skip = skip;
7786

87+
if (projection.edges) {
88+
projection.hits = projection.edges.node;
89+
delete projection.edges;
90+
}
91+
7892
const res = await searchResolver.resolve(rp);
7993

80-
let list = res.hits.hits;
94+
let list = res.hits || [];
95+
8196
const hasExtraRecords = list.length > limit;
8297
if (hasExtraRecords) list = list.slice(0, limit);
8398
const edges = list.map(node => ({ node, cursor: dataToCursor(node.sort) }));

yarn.lock

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,15 @@ babel-core@^6.0.0, babel-core@^6.24.0:
314314
slash "^1.0.0"
315315
source-map "^0.5.0"
316316

317-
babel-eslint@^7.1.1:
318-
version "7.1.1"
319-
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.1.1.tgz#8a6a884f085aa7060af69cfc77341c2f99370fb2"
317+
babel-eslint@^7.2.0:
318+
version "7.2.0"
319+
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.0.tgz#8941514b9dead06f0df71b29d5d5b193a92ee0ae"
320320
dependencies:
321-
babel-code-frame "^6.16.0"
322-
babel-traverse "^6.15.0"
323-
babel-types "^6.15.0"
324-
babylon "^6.13.0"
325-
lodash.pickby "^4.6.0"
321+
babel-code-frame "^6.22.0"
322+
babel-traverse "^6.23.1"
323+
babel-types "^6.23.0"
324+
babylon "^6.16.1"
325+
lodash "^4.17.4"
326326

327327
babel-generator@^6.18.0, babel-generator@^6.24.0:
328328
version "6.24.0"
@@ -796,7 +796,7 @@ babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0:
796796
babylon "^6.11.0"
797797
lodash "^4.2.0"
798798

799-
babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
799+
babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
800800
version "6.23.1"
801801
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48"
802802
dependencies:
@@ -810,7 +810,7 @@ babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-tr
810810
invariant "^2.2.0"
811811
lodash "^4.2.0"
812812

813-
babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0:
813+
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0:
814814
version "6.23.0"
815815
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf"
816816
dependencies:
@@ -819,11 +819,11 @@ babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22
819819
lodash "^4.2.0"
820820
to-fast-properties "^1.0.1"
821821

822-
822+
[email protected], babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0:
823823
version "6.15.0"
824824
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e"
825825

826-
babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0:
826+
babylon@^6.16.1:
827827
version "6.16.1"
828828
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3"
829829

@@ -2001,9 +2001,9 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
20012001
version "1.0.1"
20022002
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
20032003

2004-
graphql-compose@^1.17.3:
2005-
version "1.17.3"
2006-
resolved "https://registry.yarnpkg.com/graphql-compose/-/graphql-compose-1.17.3.tgz#ad4f19570aedc6647d6addb43d6f52d3804029b9"
2004+
graphql-compose@^1.18.0:
2005+
version "1.18.0"
2006+
resolved "https://registry.yarnpkg.com/graphql-compose/-/graphql-compose-1.18.0.tgz#bb28c2336bb0e4fdd87efeb92747e781a8691752"
20072007
dependencies:
20082008
babel-runtime "^6.23.0"
20092009
object-path "^0.11.4"
@@ -2865,10 +2865,6 @@ lodash.padstart@^4.1.0:
28652865
version "4.6.1"
28662866
resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"
28672867

2868-
lodash.pickby@^4.6.0:
2869-
version "4.6.0"
2870-
resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff"
2871-
28722868
lodash.restparam@^3.0.0:
28732869
version "3.6.1"
28742870
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
@@ -2877,7 +2873,7 @@ lodash@^3.6.0, lodash@^3.7.0:
28772873
version "3.10.1"
28782874
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
28792875

2880-
lodash@^4.0.0, lodash@^4.12.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.2.0, lodash@^4.3.0:
2876+
lodash@^4.0.0, lodash@^4.12.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0:
28812877
version "4.17.4"
28822878
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
28832879

0 commit comments

Comments
 (0)