11/* @flow */
22/* eslint-disable no-param-reassign */
33
4- import { Resolver , TypeComposer , isObject } from 'graphql-compose' ;
5- import type { ResolveParams , ProjectionType } from 'graphql-compose/lib/definition' ;
4+ import {
5+ Resolver ,
6+ TypeComposer ,
7+ InputTypeComposer ,
8+ isObject ,
9+ } from 'graphql-compose' ;
10+ import type {
11+ ResolveParams ,
12+ ProjectionType ,
13+ } from 'graphql-compose/lib/definition' ;
614import type { FieldsMapByElasticType } from '../mappingConverter' ;
715import ElasticApiParser from '../ElasticApiParser' ;
816import type { ElasticApiVersion } from '../ElasticApiParser' ;
@@ -20,7 +28,7 @@ export type ElasticSearchResolverOpts = {
2028
2129export default function createSearchResolver (
2230 fieldMap : FieldsMapByElasticType ,
23- sourceTC ? : TypeComposer ,
31+ sourceTC : TypeComposer ,
2432 elasticClient ?: mixed ,
2533 opts ?: ElasticSearchResolverOpts = { }
2634) : Resolver < * , * > {
@@ -43,10 +51,6 @@ export default function createSearchResolver(
4351 version : opts . elasticApiVersion || '5_0' ,
4452 prefix,
4553 } ) ;
46- const searchFC = parser . generateFieldConfig ( 'search' , {
47- index : 'cv' ,
48- type : 'cv' ,
49- } ) ;
5054
5155 const searchITC = getSearchBodyITC ( {
5256 prefix,
@@ -55,6 +59,11 @@ export default function createSearchResolver(
5559
5660 searchITC . removeField ( [ 'size' , 'from' , '_source' , 'explain' , 'version' ] ) ;
5761
62+ const searchFC = parser . generateFieldConfig ( 'search' , {
63+ index : 'cv' ,
64+ type : 'cv' ,
65+ } ) ;
66+
5867 const argsConfigMap = Object . assign ( { } , searchFC . args , {
5968 body : {
6069 type : searchITC . getType ( ) ,
@@ -68,31 +77,69 @@ export default function createSearchResolver(
6877 delete argsConfigMap . _source ; // added automatically due projection
6978 delete argsConfigMap . _sourceExclude ; // added automatically due projection
7079 delete argsConfigMap . _sourceInclude ; // added automatically due projection
80+ delete argsConfigMap . trackScores ; // added automatically due projection (is _scrore requested with sort)
7181
7282 delete argsConfigMap . size ;
7383 delete argsConfigMap . from ;
84+ // $FlowFixMe
7485 argsConfigMap . limit = 'Int' ;
86+ // $FlowFixMe
7587 argsConfigMap . skip = 'Int' ;
7688
77- const type = getSearchOutputTC ( { prefix, fieldMap, sourceTC } ) ;
78- // $FlowFixMe
79- type . addFields ( {
80- count : 'Int' ,
81- max_score : 'Float' ,
89+ const bodyITC = InputTypeComposer . create ( argsConfigMap . body . type ) ;
90+ argsConfigMap . query = bodyITC . getField ( 'query' ) ;
91+ argsConfigMap . aggs = bodyITC . getField ( 'aggs' ) ;
92+ argsConfigMap . highlight = bodyITC . getField ( 'highlight' ) ;
93+
94+ const topLevelArgs = [
95+ 'limit' ,
96+ 'skip' ,
97+ 'q' ,
98+ 'opts' ,
99+ 'query' ,
100+ 'aggs' ,
101+ 'highlight' ,
102+ ] ;
103+ argsConfigMap . opts = InputTypeComposer . create ( {
104+ name : `${ sourceTC . getTypeName ( ) } Opts` ,
105+ fields : Object . assign ( { } , argsConfigMap ) ,
106+ } ) . removeField ( topLevelArgs ) ;
107+ Object . keys ( argsConfigMap ) . forEach ( argKey => {
108+ if ( ! topLevelArgs . includes ( argKey ) ) {
109+ delete argsConfigMap [ argKey ] ;
110+ }
82111 } ) ;
83112
113+ const type = getSearchOutputTC ( { prefix, fieldMap, sourceTC } ) ;
114+ type
115+ . addFields ( {
116+ // $FlowFixMe
117+ count : 'Int' ,
118+ // $FlowFixMe
119+ max_score : 'Float' ,
120+ // $FlowFixMe
121+ hits : [ type . get ( 'hits.hits' ) ] ,
122+ } )
123+ . reorderFields ( [
124+ 'hits' ,
125+ 'count' ,
126+ 'aggregations' ,
127+ 'max_score' ,
128+ 'took' ,
129+ 'timed_out' ,
130+ '_shards' ,
131+ ] ) ;
132+
84133 // $FlowFixMe
85134 return new Resolver ( {
86135 type,
87136 name : 'search' ,
88137 kind : 'query' ,
89138 args : argsConfigMap ,
90139 resolve : async ( rp : ResolveParams < * , * > ) => {
91- const { args = { } , projection = { } } = rp ;
92-
93- if ( args . body ) {
94- args . body = prepareBodyInResolve ( args . body , fieldMap ) ;
95- }
140+ let args : Object = rp . args || { } ;
141+ const projection = rp . projection || { } ;
142+ if ( ! args . body ) args . body = { } ;
96143
97144 if ( { } . hasOwnProperty . call ( args , 'limit' ) ) {
98145 args . size = args . limit ;
@@ -105,47 +152,78 @@ export default function createSearchResolver(
105152 }
106153
107154 const { hits = { } } = projection ;
108- // $FlowFixMe
109- const { hits : hitsHits } = hits ;
110155
111- if ( typeof hitsHits === 'object' ) {
156+ if ( typeof hits === 'object' ) {
112157 // Turn on explain if in projection requested this fields:
113- if ( hitsHits . _shard || hitsHits . _node || hitsHits . _explanation ) {
114- // $FlowFixMe
158+ if ( hits . _shard || hits . _node || hits . _explanation ) {
115159 args . body . explain = true ;
116160 }
117161
118- if ( hitsHits . _version ) {
119- // $FlowFixMe
162+ if ( hits . _version ) {
120163 args . body . version = true ;
121164 }
122165
123- if ( ! hitsHits . _source ) {
124- // $FlowFixMe
166+ if ( ! hits . _source ) {
125167 args . body . _source = false ;
126168 } else {
127169 // $FlowFixMe
128- args . body . _source = toDottedList ( hitsHits . _source ) ;
170+ args . body . _source = toDottedList ( hits . _source ) ;
129171 }
172+
173+ if ( hits . _score ) {
174+ args . body . track_scores = true ;
175+ }
176+ }
177+
178+ if ( args . query ) {
179+ args . body . query = args . query ;
180+ delete args . query ;
181+ }
182+
183+ if ( args . aggs ) {
184+ args . body . aggs = args . aggs ;
185+ delete args . aggs ;
186+ }
187+
188+ if ( args . opts ) {
189+ args = {
190+ ...args . opts ,
191+ ...args ,
192+ body : { ...args . opts . body , ...args . body } ,
193+ } ;
194+ delete args . opts ;
195+ }
196+
197+ if ( args . body ) {
198+ args . body = prepareBodyInResolve ( args . body , fieldMap ) ;
130199 }
131200
132201 // $FlowFixMe
133- const res = await searchFC . resolve ( rp . source , args , rp . context , rp . info ) ;
202+ const res : any = await searchFC . resolve (
203+ rp . source ,
204+ args ,
205+ rp . context ,
206+ rp . info
207+ ) ;
134208
135209 res . count = res . hits . total ;
136210 res . max_score = res . hits . max_score ;
211+ res . hits = res . hits . hits ;
137212
138213 return res ;
139214 } ,
140- } ) ;
215+ } ) . reorderArgs ( [ 'q' , 'query' , 'aggs' , 'limit' , 'skip' ] ) ;
141216}
142217
143- export function toDottedList ( projection : ProjectionType , prev : string [ ] ) : string [ ] | boolean {
218+ export function toDottedList (
219+ projection : ProjectionType ,
220+ prev ?: string [ ]
221+ ) : string [ ] | boolean {
144222 let result = [ ] ;
145223 Object . keys ( projection ) . forEach ( k => {
146224 if ( isObject ( projection [ k ] ) ) {
147225 // $FlowFixMe
148- const tmp = toDottedList ( projection [ k ] , prev ? [ ...prev , k ] : [ k ] ) ;
226+ const tmp = toDottedList ( projection [ k ] , prev ? [ ...prev , k ] : [ k ] ) ;
149227 if ( Array . isArray ( tmp ) ) {
150228 result = result . concat ( tmp ) ;
151229 return ;
0 commit comments