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

refactor(gatsby): use GatsbyIterable + extract common tools for querying #32172

Merged
merged 8 commits into from
Jul 1, 2021

Conversation

vladar
Copy link
Contributor

@vladar vladar commented Jun 30, 2021

Description

This PR mostly affects various utilities related to querying:

  1. Extract some tools from fast-filters that could be re-used by lmdb runQuery implementation.
  2. Add convenience tools for query running as well as various convenience methods to GatsbyIterable
  3. Switch to GatsbyIterable for runQuery and various node iteration methods

There are several minor behavior changes, I'll comment on them inline.

@gatsbot gatsbot bot added the status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer label Jun 30, 2021
@vladar vladar removed the status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer label Jun 30, 2021
Base automatically changed from vladar/refactor-query-pagination to master June 30, 2021 11:30
@vladar vladar force-pushed the vladar/common-query-utils branch from d6345ce to c56a0e0 Compare June 30, 2021 12:19
Comment on lines +32 to +59
export type FilterValueNullable = // TODO: merge with DbComparatorValue
| string
| number
| boolean
| null
| undefined
| RegExp // Only valid for $regex
| Array<string | number | boolean | null | undefined>

// This is filter value in most cases
export type FilterValue =
| string
| number
| boolean
| RegExp // Only valid for $regex
| Array<string | number | boolean>

// The value is an object with arbitrary keys that are either filter values or,
// recursively, an object with the same struct. Ie. `{a: {a: {a: 2}}}`
export interface IInputQuery {
[key: string]: FilterValueNullable | IInputQuery
}
// Similar to IInputQuery except the comparator leaf nodes will have their
// key prefixed with `$` and their value, in some cases, normalized.
export interface IPreparedQueryArg {
[key: string]: FilterValueNullable | IPreparedQueryArg
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thos types are moved here from datastore/in-memory/indexing.ts and datastore/in-memory/run-fast-filters.ts

Comment on lines +171 to +208
/**
* Transforms filters coming from input GraphQL query to mongodb-compatible format
* (by prefixing comparators with "$").
*
* Example:
* { foo: { eq: 5 } } -> { foo: { $eq: 5 }}
*/
export function prepareQueryArgs(
filterFields: Array<IInputQuery> | IInputQuery = {}
): IPreparedQueryArg {
const filters = {}
Object.keys(filterFields).forEach(key => {
const value = filterFields[key]
if (_.isPlainObject(value)) {
filters[key === `elemMatch` ? `$elemMatch` : key] = prepareQueryArgs(
value as IInputQuery
)
} else {
switch (key) {
case `regex`:
if (typeof value !== `string`) {
throw new Error(
`The $regex comparator is expecting the regex as a string, not an actual regex or anything else`
)
}
filters[`$regex`] = prepareRegex(value)
break
case `glob`:
filters[`$regex`] = makeRe(value)
break
default:
filters[`$${key}`] = value
}
}
})
return filters
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also moved from datastore/in-memory/run-fast-filters.ts

@@ -297,7 +297,7 @@ class LocalNodeModel {
runQueryActivity.start()
}

const { entries, totalCount } = runFastFiltersAndSort({
const { entries, totalCount } = await getDataStore().runQuery({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now querying through datastore - the basis for future lmdb runQuery implementation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking if I'm reading things correctly and understand the plan - in this PR both "redux" and lmdb have same implementation (returning Promise.resolve(runFastFiltersAndSort(args))). In next PR(s) lmdb datastore will use its own (potentially falling back to same thing if something is impossible or just not implemented yet)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct

Comment on lines +315 to +322
return {
gqlType,
entries: entries.map(node => {
// With GatsbyIterable it happens lazily as we iterate
this.trackInlineObjectsInRootNode(node)
return node
}),
totalCount,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior change: switching from eager to lazy tracking of inline objects during iteration.

Now entries is an instance of GatsbyIterable, so we can apply this lazily. This makes a difference for lmdb because each iteration is essentially a separate query (reset cursor, re-apply filters, etc, which can be slow).

@vladar vladar marked this pull request as ready for review June 30, 2021 19:17
pieh
pieh previously approved these changes Jul 1, 2021
Copy link
Contributor

@pieh pieh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! LGTM

@pieh pieh self-assigned this Jul 1, 2021
@vladar vladar added the bot: merge on green Gatsbot will merge these PRs automatically when all tests passes label Jul 1, 2021
@gatsbybot gatsbybot merged commit e5574c8 into master Jul 1, 2021
@gatsbybot gatsbybot deleted the vladar/common-query-utils branch July 1, 2021 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bot: merge on green Gatsbot will merge these PRs automatically when all tests passes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants