@@ -102,6 +102,87 @@ const buildEsFullTextQuery = (keyword, matchType, singleFieldName) => {
102
102
} ;
103
103
} ;
104
104
105
+ /**
106
+ * Build ES query search request body based on value, keyword, matchType and fieldName
107
+ *
108
+ * @param {String } value the value to build request body for
109
+ * @param {String } keyword the keyword to query
110
+ * @param {String } matchType wildcard match or exact match
111
+ * @param {Array } fieldName the fieldName
112
+ * @return {Object } search request body that can be passed to .search api call
113
+ */
114
+ const buildEsQueryWithFilter = ( value , keyword , matchType , fieldName ) => {
115
+ let should = [ ] ;
116
+ if ( value !== 'details' && value !== 'customer' && value !== 'manager' ) {
117
+ should = _ . concat ( should , {
118
+ query_string : {
119
+ query : keyword ,
120
+ analyze_wildcard : ( matchType === MATCH_TYPE_WILDCARD ) ,
121
+ fields : fieldName ,
122
+ } ,
123
+ } ) ;
124
+ }
125
+
126
+ if ( value === 'details' ) {
127
+ should = _ . concat ( should , {
128
+ nested : {
129
+ path : 'details' ,
130
+ query : {
131
+ nested : {
132
+ path : 'details.utm' ,
133
+ query : {
134
+ query_string : {
135
+ query : keyword ,
136
+ analyze_wildcard : ( matchType === MATCH_TYPE_WILDCARD ) ,
137
+ fields : fieldName ,
138
+ } ,
139
+ } ,
140
+ } ,
141
+ } ,
142
+ } ,
143
+ } ) ;
144
+ }
145
+
146
+ if ( value === 'customer' || value === 'manager' ) {
147
+ should = _ . concat ( should , {
148
+ nested : {
149
+ path : 'members' ,
150
+ query : {
151
+ bool : {
152
+ must : [
153
+ { match : { 'members.role' : value } } ,
154
+ {
155
+ query_string : {
156
+ query : keyword ,
157
+ analyze_wildcard : ( matchType === MATCH_TYPE_WILDCARD ) ,
158
+ fields : fieldName ,
159
+ } ,
160
+ } ,
161
+ ] ,
162
+ } ,
163
+ } ,
164
+ } ,
165
+ } ) ;
166
+ }
167
+
168
+ return should ;
169
+ } ;
170
+
171
+ /**
172
+ * Prepare search request body based on wildcard query
173
+ *
174
+ * @param {String } value the value to build request body for
175
+ * @param {String } keyword the keyword to query
176
+ * @param {Array } fieldName the fieldName
177
+ * @return {Object } search request body that can be passed to .search api call
178
+ */
179
+ const setFilter = ( value , keyword , fieldName ) => {
180
+ if ( keyword . indexOf ( '*' ) > - 1 ) {
181
+ return buildEsQueryWithFilter ( value , keyword , MATCH_TYPE_WILDCARD , fieldName ) ;
182
+ }
183
+ return buildEsQueryWithFilter ( value , keyword , MATCH_TYPE_EXACT_PHRASE , fieldName ) ;
184
+ } ;
185
+
105
186
/**
106
187
* Parse the ES search criteria and prepare search request body
107
188
*
@@ -152,13 +233,40 @@ const parseElasticSearchCriteria = (criteria, fields, order) => {
152
233
}
153
234
// prepare the elasticsearch filter criteria
154
235
const boolQuery = [ ] ;
236
+ let mustQuery = [ ] ;
155
237
let fullTextQuery ;
156
238
if ( _ . has ( criteria , 'filters.id.$in' ) ) {
157
239
boolQuery . push ( {
158
240
ids : {
159
241
values : criteria . filters . id . $in ,
160
242
} ,
161
243
} ) ;
244
+ } else if ( _ . has ( criteria , 'filters.id' ) ) {
245
+ boolQuery . push ( {
246
+ term : {
247
+ id : criteria . filters . id ,
248
+ } ,
249
+ } ) ;
250
+ }
251
+
252
+ if ( _ . has ( criteria , 'filters.name' ) ) {
253
+ mustQuery = _ . concat ( mustQuery , setFilter ( 'name' , criteria . filters . name , [ 'name' ] ) ) ;
254
+ }
255
+
256
+ if ( _ . has ( criteria , 'filters.code' ) ) {
257
+ mustQuery = _ . concat ( mustQuery , setFilter ( 'details' , criteria . filters . code , [ 'details.utm.code' ] ) ) ;
258
+ }
259
+
260
+ if ( _ . has ( criteria , 'filters.customer' ) ) {
261
+ mustQuery = _ . concat ( mustQuery , setFilter ( 'customer' ,
262
+ criteria . filters . customer ,
263
+ [ 'members.firstName' , 'members.lastName' ] ) ) ;
264
+ }
265
+
266
+ if ( _ . has ( criteria , 'filters.manager' ) ) {
267
+ mustQuery = _ . concat ( mustQuery , setFilter ( 'manager' ,
268
+ criteria . filters . manager ,
269
+ [ 'members.firstName' , 'members.lastName' ] ) ) ;
162
270
}
163
271
164
272
if ( _ . has ( criteria , 'filters.status.$in' ) ) {
@@ -222,7 +330,7 @@ const parseElasticSearchCriteria = (criteria, fields, order) => {
222
330
223
331
if ( ! keyword ) {
224
332
// Not a specific field search nor an exact phrase search, do a wildcard match
225
- keyword = escapeEsKeyword ( criteria . filters . keyword ) ;
333
+ keyword = criteria . filters . keyword ;
226
334
matchType = MATCH_TYPE_WILDCARD ;
227
335
}
228
336
@@ -234,17 +342,22 @@ const parseElasticSearchCriteria = (criteria, fields, order) => {
234
342
filter : boolQuery ,
235
343
} ;
236
344
}
345
+
346
+ if ( mustQuery . length > 0 ) {
347
+ body . query . bool = _ . merge ( body . query . bool , {
348
+ must : mustQuery ,
349
+ } ) ;
350
+ }
237
351
if ( fullTextQuery ) {
238
352
body . query = _ . merge ( body . query , fullTextQuery ) ;
239
353
if ( body . query . bool ) {
240
354
body . query . bool . minimum_should_match = 1 ;
241
355
}
242
356
}
243
357
244
- if ( fullTextQuery || boolQuery . length > 0 ) {
358
+ if ( fullTextQuery || boolQuery . length > 0 || mustQuery . length > 0 ) {
245
359
searchCriteria . body = body ;
246
360
}
247
-
248
361
return searchCriteria ;
249
362
} ;
250
363
@@ -267,8 +380,7 @@ const retrieveProjects = (req, criteria, sort, ffields) => {
267
380
fields . projects . push ( 'id' ) ;
268
381
}
269
382
270
- const searchCriteria = parseElasticSearchCriteria ( criteria , fields , order ) ;
271
-
383
+ const searchCriteria = parseElasticSearchCriteria ( criteria , fields , order ) || { } ;
272
384
return new Promise ( ( accept , reject ) => {
273
385
const es = util . getElasticSearchClient ( ) ;
274
386
es . search ( searchCriteria ) . then ( ( docs ) => {
@@ -300,7 +412,8 @@ module.exports = [
300
412
'name' , 'name asc' , 'name desc' ,
301
413
'type' , 'type asc' , 'type desc' ,
302
414
] ;
303
- if ( ! util . isValidFilter ( filters , [ 'id' , 'status' , 'type' , 'memberOnly' , 'keyword' ] ) ||
415
+ if ( ! util . isValidFilter ( filters ,
416
+ [ 'id' , 'status' , 'memberOnly' , 'keyword' , 'type' , 'name' , 'code' , 'customer' , 'manager' ] ) ||
304
417
( sort && _ . indexOf ( sortableProps , sort ) < 0 ) ) {
305
418
return util . handleError ( 'Invalid filters or sort' , null , req , next ) ;
306
419
}
0 commit comments