Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(gatsby): support elemMatch as fast filter #22742

Merged
merged 16 commits into from
Apr 8, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Abstract the inside of a loop for putting a node in the right bucket
  • Loading branch information
pvdz committed Apr 7, 2020
commit 605a5b9375f7c7209b64ef5b576d482d8a32b8da
73 changes: 49 additions & 24 deletions packages/gatsby/src/redux/run-sift.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,33 +180,14 @@ const getBucketsForFilters = (filters, nodeTypeNames, filtersCache) => {

// Fail fast while trying to create and get the value-cache for each path
let every = filters.every((filter /*: DbQuery*/) => {
let {
path: chain,
query: { value: targetValue },
} = filter

let cacheKey = createTypedFilterCacheKey(nodeTypeNames, filter)

ensureIndexByTypedChain(cacheKey, chain, nodeTypeNames, filtersCache)

const filterCache = getFilterCacheByTypedChain(
getBucketsForQueryFilter(
cacheKey,
targetValue,
filtersCache
filter,
nodeTypeNames,
filtersCache,
filterCaches
)

// If we couldn't find the needle then maybe sift can, for example if the
// schema contained a proxy; `slug: String @proxy(from: "slugInternal")`
// There are also cases (and tests) where id exists with a different type
if (!filterCache) {
return false
}

// In all other cases this must be a non-empty Set because the indexing
// mechanism does not create a Set unless there's a IGatsbyNode for it
filterCaches.push(filterCache)

return true
})

if (every) {
Expand All @@ -217,6 +198,50 @@ const getBucketsForFilters = (filters, nodeTypeNames, filtersCache) => {
return undefined
}

/**
* Fetch all buckets for given query filter. That means it's not elemMatch.
*
* @param {FilterCacheKey} cacheKey
* @param {IDbQueryQuery} filter
* @param {Array<string>} nodeTypeNames
* @param {FiltersCache} filtersCache
* @param {Set<FilterCache>} filterCaches
* @returns {boolean} false means soft fail, filter must go through Sift
*/
const getBucketsForQueryFilter = (
cacheKey,
filter,
nodeTypeNames,
filtersCache,
filterCaches
) => {
let {
path: chain,
query: { value: targetValue },
} = filter

ensureIndexByTypedChain(cacheKey, chain, nodeTypeNames, filtersCache)

const filterCache = getFilterCacheByTypedChain(
cacheKey,
targetValue,
filtersCache
)

// If we couldn't find the needle then maybe sift can, for example if the
// schema contained a proxy; `slug: String @proxy(from: "slugInternal")`
// There are also cases (and tests) where id exists with a different type
if (!filterCache) {
return false
}

// In all other cases this must be a non-empty Set because the indexing
// mechanism does not create a Set unless there's a IGatsbyNode for it
filterCaches.push(filterCache)

return true
}

/**
* Filters and sorts a list of nodes using mongodb-like syntax.
*
Expand Down