name: graphile-v5-connection-filter description: Configure connection filtering in PostGraphile v5. Use when asked to "add filtering", "configure filters", "filter by column", "disable relation filters", "enable all column filters", or when setting up the connection filter plugin. compatibility: PostGraphile v5+, postgraphile-plugin-connection-filter v3+ metadata: author: constructive-io version: "1.0.0"
PostGraphile v5 Connection Filter
Configure powerful filtering capabilities for your GraphQL connections.
Official Documentation
- Connection Filter Plugin: https://github.com/graphile-contrib/postgraphile-plugin-connection-filter
- Filtering (built-in): https://postgraphile.org/postgraphile/next/filtering
When to Apply
Use this skill when:
- Setting up filtering on connections
- Configuring which columns can be filtered
- Disabling relation filters to reduce API surface
- Enabling filtering on non-indexed columns
- Understanding filter operators
Quick Start
Installation
pnpm add postgraphile-plugin-connection-filter@^3.0.0-rc.1
Basic Setup
import { PostGraphileConnectionFilterPreset } from 'postgraphile-plugin-connection-filter';
const preset: GraphileConfig.Preset = {
extends: [PostGraphileConnectionFilterPreset],
};
Filter vs Condition
PostGraphile provides two ways to filter connections:
| Feature | condition (built-in) |
filter (plugin) |
|---|---|---|
| Operators | Equality only | eq, ne, lt, gt, in, contains, etc. |
| Logical | No | and, or, not |
| Arrays | No | Yes |
| Relations | No | Optional |
Configuration Options
Schema Options
const preset: GraphileConfig.Preset = {
extends: [PostGraphileConnectionFilterPreset],
schema: {
// Disable relation filters (recommended for cleaner API)
connectionFilterRelations: false,
// Disable computed column filters
connectionFilterComputedColumns: false,
// Disable setof function filters
connectionFilterSetofFunctions: false,
// Keep logical operators (and, or, not)
connectionFilterLogicalOperators: true,
// Allow array filtering
connectionFilterArrays: true,
},
};
Disabling Relation Filters
The connectionFilterRelations: false option doesn't fully work. Use disablePlugins instead:
const preset: GraphileConfig.Preset = {
extends: [PostGraphileConnectionFilterPreset],
disablePlugins: [
'PgConnectionArgFilterBackwardRelationsPlugin',
'PgConnectionArgFilterForwardRelationsPlugin',
],
schema: {
// Set for documentation purposes
connectionFilterRelations: false,
},
};
Filter Operators
Comparison Operators
query {
users(filter: {
age: { eq: 25 } # Equal
age: { ne: 25 } # Not equal
age: { lt: 30 } # Less than
age: { lte: 30 } # Less than or equal
age: { gt: 18 } # Greater than
age: { gte: 18 } # Greater than or equal
age: { in: [25, 30, 35] } # In list
age: { notIn: [0, -1] } # Not in list
}) {
nodes { id name age }
}
}
String Operators
query {
users(filter: {
name: { eq: "John" }
name: { ne: "Jane" }
name: { like: "J%" } # SQL LIKE
name: { ilike: "j%" } # Case-insensitive LIKE
name: { notLike: "Admin%" }
name: { startsWith: "J" }
name: { endsWith: "son" }
name: { contains: "oh" }
name: { notContains: "admin" }
name: { in: ["John", "Jane"] }
}) {
nodes { id name }
}
}
Null Checks
query {
users(filter: {
deletedAt: { isNull: true } # IS NULL
email: { isNull: false } # IS NOT NULL
}) {
nodes { id name }
}
}
Logical Operators
query {
users(filter: {
or: [
{ role: { eq: "ADMIN" } },
{ role: { eq: "MODERATOR" } }
]
}) {
nodes { id name role }
}
}
query {
users(filter: {
and: [
{ age: { gte: 18 } },
{ age: { lt: 65 } }
]
}) {
nodes { id name age }
}
}
query {
users(filter: {
not: { status: { eq: "BANNED" } }
}) {
nodes { id name status }
}
}
Array Operators
query {
posts(filter: {
tags: { contains: ["important"] } # Array contains value
tags: { containedBy: ["a", "b", "c"] } # Array is subset
tags: { overlaps: ["urgent", "hot"] } # Arrays have common elements
tags: { anyEqualTo: "featured" } # Any element equals
}) {
nodes { id title tags }
}
}
Enabling Filtering on All Columns
By default, PostGraphile only allows filtering on indexed columns. To enable filtering on all columns:
export const EnableAllFilterColumnsPlugin: GraphileConfig.Plugin = {
name: 'EnableAllFilterColumnsPlugin',
version: '1.0.0',
schema: {
entityBehavior: {
pgCodecAttribute: {
inferred: {
after: ['postInferred'],
provides: ['enableAllFilters'],
callback(behavior) {
return [behavior, 'filterBy'];
},
},
},
},
},
};
Performance Warning: Filtering on non-indexed columns can cause slow queries. Monitor performance and add indexes as needed.
Disabling Filtering on Specific Columns
Use smart tags to disable filtering on sensitive columns:
COMMENT ON COLUMN users.password_hash IS E'@behavior -filterBy';
COMMENT ON COLUMN users.internal_id IS E'@behavior -filterBy';
Or use a plugin:
export const DisableSensitiveFiltersPlugin: GraphileConfig.Plugin = {
name: 'DisableSensitiveFiltersPlugin',
version: '1.0.0',
schema: {
entityBehavior: {
pgCodecAttribute: {
override: {
provides: ['disableSensitiveFilters'],
callback(behavior, [codec, attributeName]) {
const sensitivePatterns = ['password', 'secret', 'token', 'hash'];
if (sensitivePatterns.some(p => attributeName.toLowerCase().includes(p))) {
return [behavior, '-filterBy'];
}
return behavior;
},
},
},
},
},
};
Complete Preset Example
import type { GraphileConfig } from 'graphile-config';
import { PostGraphileConnectionFilterPreset } from 'postgraphile-plugin-connection-filter';
const EnableAllFilterColumnsPlugin: GraphileConfig.Plugin = {
name: 'EnableAllFilterColumnsPlugin',
version: '1.0.0',
schema: {
entityBehavior: {
pgCodecAttribute: {
inferred: {
after: ['postInferred'],
provides: ['enableAllFilters'],
callback(behavior) {
return [behavior, 'filterBy'];
},
},
},
},
},
};
export const FilterPreset: GraphileConfig.Preset = {
extends: [PostGraphileConnectionFilterPreset],
plugins: [EnableAllFilterColumnsPlugin],
disablePlugins: [
'PgConnectionArgFilterBackwardRelationsPlugin',
'PgConnectionArgFilterForwardRelationsPlugin',
],
schema: {
connectionFilterRelations: false,
connectionFilterComputedColumns: false,
connectionFilterSetofFunctions: false,
connectionFilterLogicalOperators: true,
connectionFilterArrays: true,
},
};
Troubleshooting
| Issue | Solution |
|---|---|
| Relation filters still appear | Use disablePlugins instead of schema option |
| Column not filterable | Check if column is indexed or use EnableAllFilterColumnsPlugin |
| Filter type missing | Ensure connection filter preset is in extends |
| Performance issues | Add indexes for frequently filtered columns |
Source Code References
- Connection Filter Plugin: https://github.com/graphile-contrib/postgraphile-plugin-connection-filter
- PgIndexBehaviorsPlugin (index-based filtering): https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgIndexBehaviorsPlugin.ts
References
- Connection Filter Plugin (v5 compatible): https://github.com/graphile-contrib/postgraphile-plugin-connection-filter
- PostGraphile v5 Filtering Docs: https://postgraphile.org/postgraphile/next/filtering
- See
graphile-v5-behaviorsskill for controlling filterBy behavior - See
graphile-v5-presetsskill for combining filter configuration