@@ -15,6 +15,7 @@ import { Comparator } from 'cypher-query-builder/dist/typings/clauses/where-comp
15
15
import { identity , isFunction } from 'lodash' ;
16
16
import { AbstractClass , ConditionalKeys } from 'type-fest' ;
17
17
import { DateTimeFilter } from '~/common' ;
18
+ import { variable } from '../query-augmentation/condition-variables' ;
18
19
import { collect } from './cypher-functions' ;
19
20
import { escapeLuceneSyntax , FullTextIndex } from './full-text' ;
20
21
import { ACTIVE } from './matching' ;
@@ -240,13 +241,15 @@ export const fullText =
240
241
( {
241
242
index,
242
243
normalizeInput,
244
+ separateQueryForEachWord,
243
245
escapeLucene = true ,
244
246
toLucene,
245
247
minScore = 0 ,
246
248
matchToNode,
247
249
} : {
248
250
index : ( ) => FullTextIndex ;
249
251
normalizeInput ?: ( input : string ) => string ;
252
+ separateQueryForEachWord ?: boolean ;
250
253
escapeLucene ?: boolean ;
251
254
toLucene ?: ( input : string ) => string ;
252
255
minScore ?: number ;
@@ -261,16 +264,20 @@ export const fullText =
261
264
return null ;
262
265
}
263
266
264
- let input : string = value ;
267
+ const normalized = normalizeInput
268
+ ? normalizeInput ( value as string )
269
+ : ( value as string ) ;
265
270
266
- input = normalizeInput ? normalizeInput ( input ) : input ;
267
- input = escapeLucene ? escapeLuceneSyntax ( input ) : input ;
271
+ let input = separateQueryForEachWord
272
+ ? cleanSplit ( normalized , ' ' )
273
+ : [ normalized ] ;
268
274
269
- const lucene =
270
- toLucene ?.( input ) ??
275
+ input = escapeLucene ? input . map ( escapeLuceneSyntax ) : input ;
276
+
277
+ toLucene ??= ( query ) =>
271
278
// Default to each word being matched.
272
279
// And for each word...
273
- cleanSplit ( input , ' ' )
280
+ cleanSplit ( query , ' ' )
274
281
. map ( ( term ) => {
275
282
const adjusted = [
276
283
// fuzzy (distance) search with boosted priority
@@ -285,16 +292,24 @@ export const fullText =
285
292
query
286
293
. subQuery ( ( q ) =>
287
294
q
288
- . call (
289
- index ( )
290
- . search ( lucene , { limit : 100 } )
291
- . yield ( { node : 'match' , score : true } ) ,
295
+ . unwind ( input . map ( toLucene ! ) , 'query' )
296
+ . subQuery ( 'query' , ( qq ) =>
297
+ qq
298
+ . call (
299
+ index ( )
300
+ . search ( variable ( 'query' ) , { limit : 100 } )
301
+ . yield ( { node : 'match' , score : true } ) ,
302
+ )
303
+ . where ( { score : greaterThan ( minScore ) } )
304
+ . apply ( matchToNode )
305
+ . return ( collect ( 'distinct node' ) . as ( `${ field } Matches` ) ) ,
292
306
)
293
- . where ( { score : greaterThan ( minScore ) } )
294
- . apply ( matchToNode )
295
- . return ( collect ( 'distinct node' ) . as ( `${ field } Matches` ) ) ,
307
+ . return ( collect ( `${ field } Matches` ) . as ( `${ field } MatchSets` ) ) ,
296
308
)
297
309
. with ( '*' ) ;
298
310
299
- return { node : inArray ( `${ field } Matches` , true ) } ;
311
+ return {
312
+ node : ( ) =>
313
+ `all(${ `${ field } Matches` } in ${ `${ field } MatchSets` } where node in ${ `${ field } Matches` } )` ,
314
+ } ;
300
315
} ;
0 commit comments