Skip to main content
A feature table is the GeoPackage equivalent of a vector layer. Each row in the table is a single feature: a geometry (point, line, or polygon) together with any number of typed attribute columns such as name, population, or category.

Key classes

FeatureDao

The primary access object for a feature table. Obtained from geoPackage.getFeatureDao(tableName). Use it to query, insert, update, and delete rows.

FeatureRow

Represents a single feature returned by a query. Provides typed accessors for geometry and attribute columns.

FeatureTable

Describes the schema of the feature table: its columns, geometry column name, and geometry type constraint.

FeatureColumn

Describes a single column — its name, data type, and whether it is the geometry column.

Geometry types

GeoPackage features use the geometry types defined by the OGC Simple Features standard, implemented in @ngageoint/simple-features-js:
  • Point / MultiPoint
  • LineString / MultiLineString
  • Polygon / MultiPolygon
  • GeometryCollection
  • CircularString, CompoundCurve, CurvePolygon, PolyhedralSurface, TIN, Triangle (extended types)
The geometry column in a FeatureRow is stored as GeoPackageGeometryData, a wrapper that holds the raw geometry bytes along with an optional envelope and SRS id. Call .getGeometry() to retrieve the GeoPackageGeometryData, then .getGeometryValue() for the typed Geometry object.

Getting a FeatureDao

import { GeoPackageAPI } from '@ngageoint/geopackage';

const geoPackage = await GeoPackageAPI.open('/path/to/file.gpkg');

const featureDao = geoPackage.getFeatureDao('my_layer');
console.log('Geometry column:', featureDao.getGeometryColumnName());
console.log('Feature count:', featureDao.count());

Iterating features

Query all rows with queryForAll(), which returns a FeatureResultSet. Always close the result set after use.
const resultSet = featureDao.queryForAll();
try {
  while (resultSet.moveToNext()) {
    const row: FeatureRow = resultSet.getRow();

    // Read an attribute column
    const name = row.getValue('name') as string;

    // Read the geometry
    const geometryData = row.getGeometry();
    if (geometryData != null) {
      const geometry = geometryData.getGeometry();
      console.log(name, geometry.geometryType);
    }
  }
} finally {
  resultSet.close();
}

Reading geometry from a FeatureRow

const row: FeatureRow = featureDao.queryForId(1);

// GeoPackageGeometryData — the raw wrapper
const geometryData = row.getGeometry();

// Typed Geometry object from simple-features-js
const geometry = row.getGeometryValue();

// GeometryType enum value
const type = row.getGeometryType();

// Bounding envelope
const envelope = row.getGeometryEnvelope();

GeoJSON output

The library can convert feature query results directly to GeoJSON. Use geoPackage.queryForGeoJSONFeatures() to get a result set that yields GeoJSON Feature objects.
import { GeoPackageAPI, GeoJSONResultSet } from '@ngageoint/geopackage';

const geoPackage = await GeoPackageAPI.open('/path/to/file.gpkg');

const geoJSONResultSet: GeoJSONResultSet =
  geoPackage.queryForGeoJSONFeatures('my_layer');

const featureCollection = {
  type: 'FeatureCollection',
  features: [] as Feature[],
};

try {
  while (geoJSONResultSet.moveToNext()) {
    featureCollection.features.push(geoJSONResultSet.getRow());
  }
} finally {
  geoJSONResultSet.close();
}

console.log(JSON.stringify(featureCollection));
For spatial queries — such as finding features within a bounding box — use FeatureIndexManager, which can leverage the RTree Index Extension for fast indexed lookups.

Spatial reference system

FeatureDao resolves the SRS from the GeometryColumns metadata on construction and exposes it as a Projection. Use featureDao.getBoundingBox() to get the extent in the native projection, or featureDao.getBoundingBoxWithProjection(projection) to reproject it.

Build docs developers (and LLMs) love