fix: Relation column is always present in the query result regardless of keys/excludeKeys query parameter
Pull Request
- Report security issues confidentially.
- Any contribution is under this license.
- Link this pull request to an issue.
Issue
Closes: https://github.com/parse-community/parse-server/issues/8500
Approach
This PR addresses issue #8500 where relation fields are never excluded from the returned objects when excludeKeys or specific keys are specified. This is due to the code of both mongoObjectToParseObject and postgresObjectToParseObject internally always spreading the "Relation" keys to the returned object as pointers. The approach taken in this PR is we check if specific keys are specified, and if so, we filter out the Relation fields outside. (A different approach would require passing in those specific keys into mongoObjectToParseObject and postgresObjectToParseObject so they can skip internally too). A minimal edit to GraphQL was necessary too due to previous behaviour not traversing edge.node properly for nested fields, meaning it never addressed nested fields properly, which with this PR would fail. This (hopefully) corrects the behaviour to as intended.
Tasks
- [x] Add tests
Summary by CodeRabbit
-
Bug Fixes
- Relation field selection now respects requested keys: only included relations are returned, excluded relations are omitted, and default behavior is preserved.
- GraphQL field normalization improved to handle nested edge.node paths for accurate projections.
- Consistent filtering of non-selected relation fields across storage backends for cleaner responses.
-
Tests
- Added tests validating inclusion, exclusion, and default behavior for relation field selection.
🚀 Thanks for opening this pull request!
📝 Walkthrough
Walkthrough
Adds a test for keys/excludeKeys behavior on relation fields. Updates Mongo and Postgres storage adapters to prune relation fields not requested by keys/excludeKeys. Adjusts GraphQL field normalization to strip nested "edges.node" segments. Minor formatting edits in GraphQL utilities and types.
Changes
| Cohort / File(s) | Summary |
|---|---|
Tests: Parse.Query relation keys handlingspec/ParseQuery.spec.js |
Adds a test verifying inclusion/exclusion and default behavior of relation fields when using keys and excludeKeys in Parse.Query. |
Storage: Mongo adapter relation pruningsrc/Adapters/Storage/Mongo/MongoStorageAdapter.js |
After mapping Mongo results to Parse objects, when keys are provided, removes Relation fields not present in the requested keys before returning results. |
Storage: Postgres adapter relation pruningsrc/Adapters/Storage/Postgres/PostgresStorageAdapter.js |
Captures a snapshot of requested keys (selectedKeys) and, after converting results to Parse objects, prunes relation fields that are not included in selectedKeys. |
GraphQL: query field normalizationsrc/GraphQL/loaders/parseClassQueries.js |
Field normalization in the Find flow now strips both leading edges.node. prefixes and any .edges.node occurrences within field paths to produce correct root keys. |
GraphQL: type field selection mappingsrc/GraphQL/loaders/parseClassTypes.js |
Extends relation field projection logic to strip leading and nested edges.node segments; minor reflow of _User.authDataResponse field formatting. |
GraphQL: utils formattingsrc/GraphQL/parseGraphQLUtils.js |
Minor formatting change in extractKeysAndInclude (no behavioral change). |
Sequence Diagram(s)
sequenceDiagram
autonumber
participant Client
participant API as Parse Server API
participant Adapter as StorageAdapter (Mongo/Postgres)
participant DB as Database
Client->>API: Query (where, keys/excludeKeys)
API->>Adapter: find(className, query, { keys/excludeKeys })
Adapter->>DB: Execute DB query
DB-->>Adapter: Results (raw)
Adapter->>Adapter: Map DB objects -> Parse objects
rect rgb(235,245,255)
note right of Adapter: Post-map filtering (new)
Adapter->>Adapter: If keys provided, remove Relation fields not in keys\nIf excludeKeys provided, remove excluded Relation fields
end
Adapter-->>API: Filtered Parse objects
API-->>Client: Response
sequenceDiagram
autonumber
participant GQL as GraphQL Layer
participant Loader as parseClassQueries / parseClassTypes
participant API as Parse Server API
GQL->>Loader: Selected fields (may include edges.node)
Loader->>Loader: Normalize fields: strip leading "edges.node." and any ".edges.node" segments
Loader-->>API: keys/include projection
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25 minutes
Suggested reviewers
- mtrezza
Pre-merge checks and finishing touches
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Linked Issues Check | ✅ Passed | The changes implement the core requirement from issue #8500 by filtering out relation fields when specific keys or excludeKeys are provided in both Mongo and Postgres adapters, add corresponding tests to validate this behavior, and include necessary GraphQL adjustments to handle nested edge.node paths. |
| Out of Scope Changes Check | ✅ Passed | All functional modifications directly relate to filtering relation fields in storage adapters and supporting GraphQL nested fields as described in the PR objectives, and the only additional change is a harmless formatting update in parseGraphQLUtils.js that does not affect functionality. |
| Description Check | ✅ Passed | The pull request description follows the repository template by including the required sections (“Pull Request,” “Issue,” “Approach,” and “Tasks”), correctly links to issue #8500, describes the changes made and lists the completed test task. |
| Docstring Coverage | ✅ Passed | No functions found in the changes. Docstring coverage check skipped. |
| Title Check | ✅ Passed | The title clearly summarizes the main change by stating that relation columns will now respect the keys and excludeKeys parameters and no longer always appear in query results, directly reflecting the core fix implemented in the PR. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
:white_check_mark: Snyk checks have passed. No issues have been found so far.
| Status | Scanner | Total (0) | ||||
|---|---|---|---|---|---|---|
| :white_check_mark: | Open Source Security | 0 | 0 | 0 | 0 | 0 issues |
:computer: Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.
I will reformat the title to use the proper commit message syntax.