# Query GeoJSON Features

Filter, project, sort, page, and aggregate GeoJSON features with property predicates, bbox filters, and simple spatial functions.

## Run it

- **CLI:** `gizza tool geojson-query '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"name":"Springfield","country":"US","population":120000},"geometry":{"type":"Point","coordinates":[-89.65,39.78]}},{"type":"Feature","properties":{"name":"Shelbyville","country":"US","population":30000},"geometry":{"type":"Point","coordinates":[-88.79,39.40]}}]}'`
- **Web:** https://gizza.ai/tools/geojson-query/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/geojson-query/tool.json

## Inputs

- `input` — GeoJSON _(field)_
- `query` — Query _(field)_
- `bbox` — Bounding box prefilter _(field)_
- `format` — Output _(field)_
- `indent` — JSON indentation _(field)_
- `include_bbox` — Include output bbox _(field)_

## Output

- Query result (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `input` — GeoJSON
- `query` — Query
- `bbox` — Bounding box prefilter
- `format` — Output
- `indent` — JSON indentation
- `include_bbox` — Include output bbox

Example: `https://gizza.ai/tools/geojson-query/?input=%7B%22type%22%3A%22FeatureCollection%22%2C%22features%22%3A%5B%7B%22type%22%3A%22Feature%22%2C%22properties%22%3A%7B%22name%22%3A%22Springfield%22%2C%22country%22%3A%22US%22%2C%22population%22%3A120000%7D%2C%22geometry%22%3A%7B%22type%22%3A%22Point%22%2C%22coordinates%22%3A%5B-89.65%2C39.78%5D%7D%7D%2C%7B%22type%22%3A%22Feature%22%2C%22properties%22%3A%7B%22name%22%3A%22Shelbyville%22%2C%22country%22%3A%22US%22%2C%22population%22%3A30000%7D%2C%22geometry%22%3A%7B%22type%22%3A%22Point%22%2C%22coordinates%22%3A%5B-88.79%2C39.40%5D%7D%7D%5D%7D&query=SELECT%20name%2C%20population%20WHERE%20country%20%3D%20%27US%27%20ORDER%20BY%20population%20DESC%20LIMIT%2010&bbox=-90%2C39%2C-88%2C40&format=geojson&indent=0&include_bbox=true`

---

## About this tool

GeoJSON Query is a local, paste-and-run feature filter for GeoJSON files. It accepts a `FeatureCollection`, one `Feature`, a bare geometry, or an array of features, then applies a compact SQL-like query language without uploading data or needing PostGIS.

Use it for quick map-data questions such as:

- `SELECT name, population WHERE population > 100000 ORDER BY population DESC`
- `WHERE bbox(-90, 39, -88, 40)` to keep features whose bounding boxes intersect an area
- `WHERE contains(-89.5, 39.5)` to find polygon features containing a point
- `SELECT country, count(*) AS features GROUP BY country ORDER BY features DESC`

The query language supports `SELECT`, `WHERE`, `GROUP BY`, `ORDER BY`, `LIMIT`, and `OFFSET`. Property predicates include `=`, `!=`, `<`, `<=`, `>`, `>=`, `IN`, `LIKE`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, and `IS NULL`. Spatial helpers include `bbox()`/`intersects()`, `within()`, `contains(lon, lat)`, and `near(lon, lat, km)`.

All coordinates are interpreted as WGS84 longitude/latitude, matching RFC 7946 GeoJSON. The tool does not reproject data or implement full CQL2; it is designed for deterministic client-side filtering, projection, sorting, paging, and small aggregates.

## FAQ

<details>
<summary>What GeoJSON shapes can I paste?</summary>

You can paste a `FeatureCollection`, a single `Feature`, a bare GeoJSON geometry, or an array of `Feature` objects. Bare geometries are wrapped as one feature with empty properties so they can be queried with `$type` and spatial predicates.

</details>

<details>
<summary>What does the optional bbox field do?</summary>

The `bbox` field is a convenience prefilter written as `minLon,minLat,maxLon,maxLat`. It is ANDed with the query's own `WHERE` clause and uses intersects semantics, so a feature is kept if its computed bounding box overlaps the supplied box.

</details>

<details>
<summary>Can this replace PostGIS, CQL2, or a GIS engine?</summary>

No. It is intentionally a self-contained browser/CLI tool for one GeoJSON input. It does not reproject CRS values, perform polygon-polygon overlay, run joins, or implement full OGC CQL2. Use PostGIS, DuckDB Spatial, or a GIS engine for those heavier workflows.

</details>

<details>
<summary>Why do aggregate queries return JSON rows instead of GeoJSON?</summary>

Aggregates such as `count(*)` and `sum(population)` produce tabular rows, not map features. When a query contains aggregates or `GROUP BY`, `geojson` output automatically behaves like JSON rows; choose `csv` when you want spreadsheet-ready output.

</details>

## Related tools

- [Point in Polygon Checker](https://gizza.ai/tools/geofence-check/): Test latitude/longitude points against a polygon geofence. Paste GeoJSON or lat,lon lines, choose boundary handling, and export text, CSV, or JSON.
- [Convert GeoJSON, WKT, and WKB Geometries](https://gizza.ai/tools/geojson-wkt/): Convert geometries between GeoJSON, WKT/EWKT, and WKB/EWKB with SRID, precision, endian, and multi-feature controls.
- [Query Result Formatter](https://gizza.ai/tools/query-result-formatter/): Turn raw query result rows — a JSON array, CSV, or TSV — into a clean, aligned Markdown or ASCII table for docs and chat.
- [ARFF Converter](https://gizza.ai/tools/arff-converter/): Convert Weka ARFF datasets to CSV and CSV tables back to ARFF locally — nominal attributes, numeric types, dates, sparse rows, missing values, and type rows.
- [Beancount to CSV Converter](https://gizza.ai/tools/beancount-to-csv/): Flatten Beancount or Ledger journal postings into spreadsheet-ready CSV, then rebuild a simple journal from that flat CSV schema.
