@@ -12,33 +12,22 @@ const {
12
12
dbQueryToSiftQuery,
13
13
} = require ( `../db/common/query` )
14
14
const {
15
+ ensureEmptyFilterCache,
15
16
ensureIndexByQuery,
16
17
ensureIndexByElemMatch,
17
18
getNodesFromCacheByValue,
18
19
addResolvedNodes,
19
20
getNode : siftGetNode ,
20
21
} = require ( `./nodes` )
21
22
22
- const FAST_OPS = [
23
- `$eq` ,
24
- `$ne` ,
25
- `$lt` ,
26
- `$lte` ,
27
- `$gt` ,
28
- `$gte` ,
29
- `$in` ,
30
- `$nin` ,
31
- `$regex` , // Note: this includes $glob
32
- ]
33
-
34
23
// More of a testing mechanic, to verify whether last runSift call used Sift
35
24
let lastFilterUsedSift = false
36
25
37
26
/**
38
27
* Creates a key for one filterCache inside FiltersCache
39
28
*
40
29
* @param {Array<string> } typeNames
41
- * @param {DbQuery } filter
30
+ * @param {DbQuery | null } filter If null the key will have empty path/op parts
42
31
* @returns {FilterCacheKey } (a string: `types.join()/path.join()/operator` )
43
32
*/
44
33
const createFilterCacheKey = ( typeNames , filter ) => {
@@ -147,10 +136,15 @@ function handleMany(siftArgs, nodes) {
147
136
*
148
137
* @param {Array<DbQuery> } filters Resolved. (Should be checked by caller to exist)
149
138
* @param {Array<string> } nodeTypeNames
150
- * @param {FiltersCache } filtersCache
151
- * @returns {Array<IGatsbyNode> | undefined }
139
+ * @param {undefined | null | FiltersCache } filtersCache
140
+ * @returns {Array<IGatsbyNode> | null }
152
141
*/
153
- const runFiltersWithoutSift = ( filters , nodeTypeNames , filtersCache ) => {
142
+ const filterWithoutSift = ( filters , nodeTypeNames , filtersCache ) => {
143
+ if ( ! filtersCache ) {
144
+ // If no filter cache is passed on, explicitly don't use one
145
+ return null
146
+ }
147
+
154
148
const nodesPerValueSets /*: Array<Set<IGatsbyNode>> */ = getBucketsForFilters (
155
149
filters ,
156
150
nodeTypeNames ,
@@ -159,7 +153,7 @@ const runFiltersWithoutSift = (filters, nodeTypeNames, filtersCache) => {
159
153
160
154
if ( ! nodesPerValueSets ) {
161
155
// Let Sift take over as fallback
162
- return undefined
156
+ return null
163
157
}
164
158
165
159
// Put smallest last (we'll pop it)
@@ -188,11 +182,14 @@ const runFiltersWithoutSift = (filters, nodeTypeNames, filtersCache) => {
188
182
// case for all value pairs? How likely is that to ever be reused?
189
183
190
184
if ( result . length === 0 ) {
191
- return undefined
185
+ return null
192
186
}
193
187
return result
194
188
}
195
189
190
+ // Not a public API
191
+ exports . filterWithoutSift = filterWithoutSift
192
+
196
193
/**
197
194
* @param {Array<DbQuery> } filters
198
195
* @param {Array<string> } nodeTypeNames
@@ -256,11 +253,7 @@ const getBucketsForQueryFilter = (
256
253
) => {
257
254
let {
258
255
path : filterPath ,
259
- query : {
260
- // Note: comparator is verified to be a FilterOp in filterWithoutSift
261
- comparator /*: as FilterOp*/ ,
262
- value : filterValue ,
263
- } ,
256
+ query : { comparator /*: as FilterOp*/ , value : filterValue } ,
264
257
} = filter
265
258
266
259
if ( ! filtersCache . has ( filterCacheKey ) ) {
@@ -323,10 +316,6 @@ const collectBucketForElemMatch = (
323
316
}
324
317
}
325
318
326
- if ( ! FAST_OPS . includes ( comparator ) ) {
327
- return false
328
- }
329
-
330
319
if ( ! filtersCache . has ( filterCacheKey ) ) {
331
320
ensureIndexByElemMatch (
332
321
comparator ,
@@ -411,7 +400,7 @@ exports.didLastFilterUseSift = function _didLastFilterUseSift() {
411
400
* @param {Array<string> } nodeTypeNames
412
401
* @param {undefined | null | FiltersCache } filtersCache
413
402
* @param resolvedFields
414
- * @returns {Array<IGatsbyNode> | undefined } Collection of results. Collection
403
+ * @returns {Array<IGatsbyNode> | null } Collection of results. Collection
415
404
* will be limited to 1 if `firstOnly` is true
416
405
*/
417
406
const applyFilters = (
@@ -444,7 +433,27 @@ const applyFilters = (
444
433
}
445
434
}
446
435
447
- const result = filterWithoutSift ( filters , nodeTypeNames , filtersCache )
436
+ if ( filtersCache && filters . length === 0 ) {
437
+ let filterCacheKey = createFilterCacheKey ( nodeTypeNames , null )
438
+ if ( ! filtersCache . has ( filterCacheKey ) ) {
439
+ ensureEmptyFilterCache ( filterCacheKey , nodeTypeNames , filtersCache )
440
+ }
441
+
442
+ const cache = filtersCache . get ( filterCacheKey ) . meta . nodesUnordered
443
+
444
+ lastFilterUsedSift = false
445
+
446
+ if ( firstOnly || cache . length ) {
447
+ return cache . slice ( 0 )
448
+ }
449
+ return null
450
+ }
451
+
452
+ const result /*: Array<IGatsbyNode> | null */ = filterWithoutSift (
453
+ filters ,
454
+ nodeTypeNames ,
455
+ filtersCache
456
+ )
448
457
449
458
lastFilterUsedSift = false
450
459
if ( result ) {
@@ -458,7 +467,7 @@ const applyFilters = (
458
467
}
459
468
lastFilterUsedSift = true
460
469
461
- const siftResult = filterWithSift (
470
+ const siftResult /*: Array<IGatsbyNode> | null */ = filterWithSift (
462
471
filters ,
463
472
firstOnly ,
464
473
nodeTypeNames ,
@@ -493,54 +502,14 @@ const filterToStats = (
493
502
}
494
503
}
495
504
496
- /**
497
- * Check if filter op is supported (not all are). If so, uses custom
498
- * fast indexes based on filter and types and returns any result it finds.
499
- * If conditions are not met or no nodes are found, returns undefined and
500
- * a slow run through Sift is executed instead.
501
- * This function is a noop if no filter cache is given to it.
502
- *
503
- * @param {Array<DbQuery> } filters Resolved. (Should be checked by caller to exist)
504
- * @param {Array<string> } nodeTypeNames
505
- * @param {undefined | null | FiltersCache } filtersCache
506
- * @returns {Array<IGatsbyNode> | undefined } Collection of results
507
- */
508
- const filterWithoutSift = ( filters , nodeTypeNames , filtersCache ) => {
509
- if ( ! filtersCache ) {
510
- // If no filter cache is passed on, explicitly don't use one
511
- return undefined
512
- }
513
-
514
- if ( filters . length === 0 ) {
515
- // If no filters are given, go through Sift. This does not appear to be
516
- // slower than shortcutting it here.
517
- return undefined
518
- }
519
-
520
- if (
521
- filters . some (
522
- filter =>
523
- filter . type === `query` && ! FAST_OPS . includes ( filter . query . comparator )
524
- )
525
- ) {
526
- // If there's a filter with non-supported op, stop now.
527
- return undefined
528
- }
529
-
530
- return runFiltersWithoutSift ( filters , nodeTypeNames , filtersCache )
531
- }
532
-
533
- // Not a public API
534
- exports . filterWithoutSift = filterWithoutSift
535
-
536
505
/**
537
506
* Use sift to apply filters
538
507
*
539
508
* @param {Array<DbQuery> } filters Resolved
540
509
* @param {boolean } firstOnly
541
510
* @param {Array<string> } nodeTypeNames
542
511
* @param resolvedFields
543
- * @returns {Array<IGatsbyNode> | undefined | null } Collection of results.
512
+ * @returns {Array<IGatsbyNode> | null } Collection of results.
544
513
* Collection will be limited to 1 if `firstOnly` is true
545
514
*/
546
515
const filterWithSift = ( filters , firstOnly , nodeTypeNames , resolvedFields ) => {
@@ -566,7 +535,7 @@ const filterWithSift = (filters, firstOnly, nodeTypeNames, resolvedFields) => {
566
535
* @param {Array<string> } nodeTypeNames
567
536
* @param resolvedFields
568
537
* @param {function(id: string): IGatsbyNode | undefined } getNode
569
- * @returns {Array<IGatsbyNode> | undefined | null } Collection of results.
538
+ * @returns {Array<IGatsbyNode> | null } Collection of results.
570
539
* Collection will be limited to 1 if `firstOnly` is true
571
540
*/
572
541
const runSiftOnNodes = (
@@ -605,13 +574,14 @@ const runSiftOnNodes = (
605
574
/**
606
575
* Given a list of filtered nodes and sorting parameters, sort the nodes
607
576
*
608
- * @param {Array<IGatsbyNode> | undefined | null } nodes Pre-filtered list of nodes
577
+ * @param {Array<IGatsbyNode> | null } nodes Pre-filtered list of nodes
609
578
* @param {Object | undefined } sort Sorting arguments
610
579
* @param resolvedFields
611
580
* @returns {Array<IGatsbyNode> | undefined | null } Same as input, except sorted
612
581
*/
613
582
const sortNodes = ( nodes , sort , resolvedFields , stats ) => {
614
- if ( ! sort || nodes ?. length <= 1 ) {
583
+ // `undefined <= 1` and `undefined > 1` are both false so invert the result...
584
+ if ( ! sort || ! ( nodes ?. length > 1 ) ) {
615
585
return nodes
616
586
}
617
587
0 commit comments