| 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
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: {
connectionFilterRelations: false,
connectionFilterComputedColumns: false,
connectionFilterSetofFunctions: false,
connectionFilterLogicalOperators: true,
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: {
connectionFilterRelations: false,
},
};
Filter Operators
Comparison Operators
query {
users(filter: {
age: { eq: 25 }
age: { ne: 25 }
age: { lt: 30 }
age: { lte: 30 }
age: { gt: 18 }
age: { gte: 18 }
age: { in: [25, 30, 35] }
age: { notIn: [0, -1] }
}) {
nodes { id name age }
}
}
String Operators
query {
users(filter: {
name: { eq: "John" }
name: { ne: "Jane" }
name: { like: "J%" }
name: { ilike: "j%" }
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 }
email: { isNull: false }
}) {
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"] }
tags: { containedBy: ["a", "b", "c"] }
tags: { overlaps: ["urgent", "hot"] }
tags: { anyEqualTo: "featured" }
}) {
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
References