Skip to content

Commit

Permalink
feat(SearchResolver): Add SearchResolver generated from mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
nodkz committed Mar 21, 2017
1 parent c2b2d60 commit fef17f0
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 50 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
},
"devDependencies": {
"babel-cli": "^6.24.0",
"babel-eslint": "^7.1.1",
"babel-eslint": "^7.2.0",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.22.0",
"babel-preset-env": "^1.2.2",
Expand All @@ -48,7 +48,7 @@
"express-graphql": "^0.6.3",
"flow-bin": "^0.42.0",
"graphql": "^0.9.1",
"graphql-compose": "^1.17.3",
"graphql-compose": "^1.18.0",
"jest": "^19.0.2",
"jest-babel": "^1.0.1",
"npm-run-all": "^4.0.1",
Expand Down
45 changes: 26 additions & 19 deletions src/elasticDSL/Commons/FieldNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ export function getAllAsFieldConfigMap(opts: mixed, fc: mixed) {
return getFieldConfigMap(opts, ['_all'], fc);
}

export function getFieldNamesByElasticType(
fieldMap: any,
types: ElasticDataType[]
): string[] {
const fieldNames = [];
types.forEach(type => {
if (typeof fieldMap[type] === 'object') {
Object.keys(fieldMap[type]).forEach(fieldName => {
fieldNames.push(fieldName);
});
}
});
return fieldNames;
}

export function getFieldNamesType(
opts: mixed,
types: ElasticDataType[],
Expand Down Expand Up @@ -134,19 +149,15 @@ function getEnumValues(
addAll: boolean = false
): GraphQLEnumValueConfigMap {
const values = {};
types.forEach(type => {
if (addAll) {
values._all = {
value: '_all',
};
}
if (typeof fieldMap[type] === 'object') {
Object.keys(fieldMap[type]).forEach(fieldName => {
values[fieldName] = {
value: fieldName.replace('__', '.'),
};
});
}
if (addAll) {
values._all = {
value: '_all',
};
}
getFieldNamesByElasticType(fieldMap, types).forEach(fieldName => {
values[fieldName] = {
value: fieldName.replace('__', '.'),
};
});
return values;
}
Expand Down Expand Up @@ -175,12 +186,8 @@ export function getFieldConfigMap(
// $FlowFixMe
fcMap._all = fc;
}
types.forEach(type => {
if (typeof opts.fieldMap[type] === 'object') {
Object.keys(opts.fieldMap[type]).forEach(fieldName => {
fcMap[fieldName] = fc;
});
}
getFieldNamesByElasticType(opts.fieldMap, types).forEach(fieldName => {
fcMap[fieldName] = fc;
});

if (Object.keys(fcMap).length === 0) {
Expand Down
3 changes: 2 additions & 1 deletion src/elasticDSL/SearchBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InputTypeComposer } from 'graphql-compose';
import type { FieldsMapByElasticType } from '../mappingConverter';
import { getQueryITC, prepareQueryInResolve } from './Query/Query';
import { getAggsITC, prepareAggsInResolve } from './Aggs/Aggs';
import { getSortITC } from './Sort';
import { getTypeName, getOrSetType, desc } from '../utils';

export type SearchOptsT = {
Expand Down Expand Up @@ -31,7 +32,7 @@ export function getSearchBodyITC(opts: SearchOptsT = {}): InputTypeComposer {
aggs: () => getAggsITC(opts),
size: 'Int',
from: 'Int',
sort: 'JSON',
sort: () => [getSortITC(opts)],
_source: 'JSON',
script_fields: 'JSON',
post_filter: () => getQueryITC(opts),
Expand Down
62 changes: 62 additions & 0 deletions src/elasticDSL/Sort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* @flow */

import { InputTypeComposer } from 'graphql-compose';
import { GraphQLEnumType } from 'graphql';
import { getTypeName, getOrSetType } from '../utils';
import { getFieldNamesByElasticType } from './Commons/FieldNames';

const sortableTypes = [
'byte',
'short',
'integer',
'long',
'double',
'float',
'half_float',
'scaled_float',
'token_count',
'date',
'boolean',
'ip',
'keyword',
];

export function getSortITC(opts: any = {}): InputTypeComposer | string {
const name = getTypeName('SortEnum', opts);
const description = 'Sortable fields from mapping';

if (!opts.fieldMap) {
return 'JSON';
}

return getOrSetType(name, () => {
const sortableFields = getFieldNamesByElasticType(
opts.fieldMap,
sortableTypes
);
if (sortableFields.length === 0) {
return 'JSON';
}

const values = {
_score: {
value: '_score',
},
};
sortableFields.forEach(fieldName => {
const dottedName = fieldName.replace('__', '.');
values[`${fieldName}__asc`] = {
value: { [dottedName]: 'asc' },
};
values[`${fieldName}__desc`] = {
value: { [dottedName]: 'desc' },
};
});

return new GraphQLEnumType({
name,
description,
values,
});
});
}
18 changes: 13 additions & 5 deletions src/resolvers/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,18 @@ export default function createSearchResolver(
const bodyITC = InputTypeComposer.create(argsConfigMap.body.type);
argsConfigMap.query = bodyITC.getField('query');
argsConfigMap.aggs = bodyITC.getField('aggs');
argsConfigMap.sort = bodyITC.getField('sort');
argsConfigMap.highlight = bodyITC.getField('highlight');

const topLevelArgs = [
'limit',
'skip',
'q',
'opts',
'query',
'sort',
'limit',
'skip',
'aggs',
'highlight',
'opts',
];
argsConfigMap.opts = InputTypeComposer.create({
name: `${sourceTC.getTypeName()}Opts`,
Expand All @@ -111,14 +113,15 @@ export default function createSearchResolver(
});

const type = getSearchOutputTC({ prefix, fieldMap, sourceTC });
const hitsType = type.get('hits.hits');
type
.addFields({
// $FlowFixMe
count: 'Int',
// $FlowFixMe
max_score: 'Float',
// $FlowFixMe
hits: [type.get('hits.hits')],
hits: hitsType ? [hitsType] : 'JSON',
})
.reorderFields([
'hits',
Expand Down Expand Up @@ -185,6 +188,11 @@ export default function createSearchResolver(
delete args.aggs;
}

if (args.sort) {
args.body.sort = args.sort;
delete args.sort;
}

if (args.opts) {
args = {
...args.opts,
Expand Down Expand Up @@ -212,7 +220,7 @@ export default function createSearchResolver(

return res;
},
}).reorderArgs(['q', 'query', 'aggs', 'limit', 'skip']);
}).reorderArgs(['q', 'query', 'sort', 'limit', 'skip', 'aggs']);
}

export function toDottedList(
Expand Down
21 changes: 18 additions & 3 deletions src/resolvers/searchConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@ export default function createSearchConnectionResolver(
before: 'String',
})
.removeArg(['limit', 'skip'])
.reorderArgs(['q', 'query', 'aggs', 'first', 'after', 'last', 'before']);
.reorderArgs([
'q',
'query',
'sort',
'aggs',
'first',
'after',
'last',
'before',
]);

const searchType = searchResolver.getTypeComposer();
const typeName = searchType.getTypeName();
Expand All @@ -43,7 +52,7 @@ export default function createSearchConnectionResolver(
);

resolver.resolve = async rp => {
const { args = {} } = rp;
const { args = {}, projection = {} } = rp;

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

if (projection.edges) {
projection.hits = projection.edges.node;
delete projection.edges;
}

const res = await searchResolver.resolve(rp);

let list = res.hits.hits;
let list = res.hits || [];

const hasExtraRecords = list.length > limit;
if (hasExtraRecords) list = list.slice(0, limit);
const edges = list.map(node => ({ node, cursor: dataToCursor(node.sort) }));
Expand Down
36 changes: 16 additions & 20 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -314,15 +314,15 @@ babel-core@^6.0.0, babel-core@^6.24.0:
slash "^1.0.0"
source-map "^0.5.0"

babel-eslint@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.1.1.tgz#8a6a884f085aa7060af69cfc77341c2f99370fb2"
babel-eslint@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.0.tgz#8941514b9dead06f0df71b29d5d5b193a92ee0ae"
dependencies:
babel-code-frame "^6.16.0"
babel-traverse "^6.15.0"
babel-types "^6.15.0"
babylon "^6.13.0"
lodash.pickby "^4.6.0"
babel-code-frame "^6.22.0"
babel-traverse "^6.23.1"
babel-types "^6.23.0"
babylon "^6.16.1"
lodash "^4.17.4"

babel-generator@^6.18.0, babel-generator@^6.24.0:
version "6.24.0"
Expand Down Expand Up @@ -796,7 +796,7 @@ babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0:
babylon "^6.11.0"
lodash "^4.2.0"

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:
babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
version "6.23.1"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48"
dependencies:
Expand All @@ -810,7 +810,7 @@ babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-tr
invariant "^2.2.0"
lodash "^4.2.0"

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:
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf"
dependencies:
Expand All @@ -819,11 +819,11 @@ babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22
lodash "^4.2.0"
to-fast-properties "^1.0.1"

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

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

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

graphql-compose@^1.17.3:
version "1.17.3"
resolved "https://registry.yarnpkg.com/graphql-compose/-/graphql-compose-1.17.3.tgz#ad4f19570aedc6647d6addb43d6f52d3804029b9"
graphql-compose@^1.18.0:
version "1.18.0"
resolved "https://registry.yarnpkg.com/graphql-compose/-/graphql-compose-1.18.0.tgz#bb28c2336bb0e4fdd87efeb92747e781a8691752"
dependencies:
babel-runtime "^6.23.0"
object-path "^0.11.4"
Expand Down Expand Up @@ -2865,10 +2865,6 @@ lodash.padstart@^4.1.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"

lodash.pickby@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff"

lodash.restparam@^3.0.0:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
Expand All @@ -2877,7 +2873,7 @@ lodash@^3.6.0, lodash@^3.7.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"

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:
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:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"

Expand Down

0 comments on commit fef17f0

Please sign in to comment.