4.2 KiB
4.2 KiB
| title | aliases | tags | sources | created | updated | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Point Field |
|
|
|
2026-05-15 | 2026-05-15 |
Overview
The Point field stores a [longitude, latitude] coordinate pair. Internally it matches the GeoJSON Point structure; the Payload API simplifies it to a two-element array.
{
name: 'location',
type: 'point',
label: 'Location',
}
SQLite not supported. Point field only works with MongoDB and PostgreSQL.
The field automatically creates a 2dsphere index for efficient geospatial queries. To disable: index: false.
Config Options
| Option | Notes |
|---|---|
name * |
Property name in DB |
label |
Admin Panel label + GraphQL type name |
index |
Defaults to 2dsphere; set false to disable |
unique |
DB-level unique index |
validate |
Custom validation function (runs on client + server) |
saveToJWT |
Include value in user JWT (top-level fields only) |
hooks |
Field-level hooks |
access |
Field-level access control |
hidden |
Hide from all APIs/Admin (still saved to DB) |
defaultValue |
Default coordinate pair |
localized |
Requires localization enabled in base config |
required |
Require non-null value |
virtual |
true = no DB column; or path string to link with a relationship |
typescriptSchema |
Override generated TS type with JSON schema |
custom |
Extension point for plugins |
Geospatial Queries
near — distance-based sort
Returns documents sorted by proximity (nearest first):
payload.find({
collection: 'locations',
where: {
point: {
near: [longitude, latitude, maxDistance, minDistance],
},
},
})
within — polygon containment
Returns points that fall inside a GeoJSON polygon:
const polygon = [
[9.0, 19.0], // bottom-left
[9.0, 21.0], // top-left
[11.0, 21.0], // top-right
[11.0, 19.0], // bottom-right
[9.0, 19.0], // close polygon
]
payload.find({
collection: 'points',
where: {
point: {
within: { type: 'Polygon', coordinates: [polygon] },
},
},
})
intersects — polygon intersection
Returns points that intersect a GeoJSON polygon (same syntax as within, different operator):
payload.find({
collection: 'points',
where: {
point: {
intersects: { type: 'Polygon', coordinates: [polygon] },
},
},
})
Custom Components
Field
// Server
import { PointField } from '@payloadcms/ui'
import type { PointFieldServerComponent } from 'payload'
export const CustomPointFieldServer: PointFieldServerComponent = ({
clientField, path, schemaPath, permissions,
}) => <PointField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
// Client
'use client'
import { PointField } from '@payloadcms/ui'
import type { PointFieldClientComponent } from 'payload'
export const CustomPointFieldClient: PointFieldClientComponent = (props) => <PointField {...props} />
Label
// Server
import { FieldLabel } from '@payloadcms/ui'
import type { PointFieldLabelServerComponent } from 'payload'
export const CustomPointFieldLabelServer: PointFieldLabelServerComponent = ({ clientField, path }) => (
<FieldLabel label={clientField?.label || clientField?.name} path={path} required={clientField?.required} />
)
Key Takeaways
- Data format:
[longitude, latitude]— longitude first (GeoJSON convention) - Not supported in SQLite — MongoDB and PostgreSQL only
- Auto
2dsphereindex — required fornear/within/intersectsqueries; disable withindex: false - Three geo operators:
near(proximity sort),within(containment),intersects(polygon intersection) - GeoJSON polygons must close — last coordinate must match the first
- Combine with wiki/payloadcms/database-indexes for compound geospatial queries
- See wiki/payloadcms/fields-overview for shared config options (virtual, hooks, access, saveToJWT)
Sources
raw/fields__point.md— official Payload CMS Point Field docs- https://payloadcms.com/docs/fields/point