Prompt 20 · Lesson 01 · Coordinate and GeoJSON semantics

GeoJSON, Legacy Coordinate Pairs, Coordinate Reference Expectations, and Data Validation

Model coordinates correctly before asking the database a spatial question.

Intermediate110–170 minutesGeoJSON/validation labMongoDB 8.3.8 · mongosh 2.10.0 · PyMongo 4.17.0Last reviewed: September 2026

Learning objectives

01

Represent AtlasMart locations with valid GeoJSON and legacy coordinate pairs and state when each representation is appropriate.

02

Explain longitude-first ordering, WGS84/EPSG:4326 expectations, supported geometry types, and polygon closure/winding considerations.

03

Distinguish a syntactically valid but semantically reversed coordinate from a truly invalid coordinate that a 2dsphere index rejects.

04

Use schema/index/application checks together instead of assuming MongoDB can infer business geography from two numbers.

05

Explain the MongoDB 8.2+ precedence rule when a location subdocument contains both legacy numeric coordinates and GeoJSON.

Reproducible lab baseline

This lesson pins MongoDB Community Server 8.3.8 using mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim, mongosh 2.10.0, and PyMongo 4.17.0 where client measurement is useful. The mandatory lab is a disposable loopback-only standalone on port 27165 named atlasmart-ch20-l1. Authentication and TLS are disabled only for this isolated learning container. Default read/write concern and primary read preference apply. FCV is observed and never changed. Atlas, Search, Vector Search, KMS, and Enterprise Advanced are not required. MongoDB 8.3 creates new 2dsphere indexes as index version 4; downgrading FCV below 8.3 requires dropping those version-4 indexes first. Product labs were not executed in this generation environment, so distance, explain, index-size, and latency evidence that depends on runtime must be measured locally rather than copied as invented output. Lesson 1 uses synthetic AtlasMart Baku-area coordinates. Their business labels are fictional; the lab tests geometry semantics, not real-world store accuracy.

1. Two numbers are not enough to define a location

AtlasMart wants to store shops, pickup points, service polygons, delivery routes, and warehouse-floor coordinates. A field such as [49.8671,40.4093] is meaningless unless the application and database agree on coordinate order and geometry. For geographic longitude/latitude data MongoDB follows GeoJSON conventions: longitude first, latitude second. GeoJSON queries use the WGS84 reference system, and $geometry uses EPSG:4326 by default.

A GeoJSON object contains a type and coordinates. MongoDB supports Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection. A legacy coordinate pair is normally an array [x,y]; for longitude/latitude that still means [longitude,latitude], but legacy pairs are primarily the representation used by the planar 2d index.

Representation Example Mental model
GeoJSON Point {type:"Point",coordinates:[49.8671,40.4093]} Earth-like spherical geometry with 2dsphere.
GeoJSON Polygon closed coordinate rings Geographic areas/zones on the sphere.
Legacy pair [125,44] Ordered two-dimensional coordinates; typically flat 2d workloads.
Reversed lon/lat [40.4093,49.8671] May still be numerically valid, but represents the wrong place.

2. Build a validated public model and inspect index-time validation

start the disposable MongoDB 8.3.8 lab
docker rm -f atlasmart-ch20-l1 2>/dev/null || truedocker volume rm atlasmart-ch20-l1-data 2>/dev/null || truedocker run -d --name atlasmart-ch20-l1 \  -p 127.0.0.1:27165:27017 \  -v atlasmart-ch20-l1-data:/data/db \  mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim \  --bind_ip_alldocker exec atlasmart-ch20-l1 mongosh --quiet --eval 'printjson(db.adminCommand({buildInfo:1}).version);printjson(db.adminCommand({getParameter:1,featureCompatibilityVersion:1}).featureCompatibilityVersion);' 
create AtlasMart store locations and a 2dsphere index
const d=db.getSiblingDB("atlasmart");d.store_locations_ch20_l1.drop();d.createCollection("store_locations_ch20_l1",{  validator: {$jsonSchema:{    bsonType:"object", required:["tenantId","storeId","location"],    properties:{      tenantId:{bsonType:"string"}, storeId:{bsonType:"string"},      location:{bsonType:"object",required:["type","coordinates"],properties:{        type:{enum:["Point"]},        coordinates:{bsonType:"array",minItems:2,maxItems:2,items:{bsonType:["double","int","long","decimal"]}}      }}    }  }}});d.store_locations_ch20_l1.createIndex({location:"2dsphere"},{name:"location_2dsphere"});d.store_locations_ch20_l1.insertMany([  {_id:"s1",tenantId:"tenant-a",storeId:"baku-center",location:{type:"Point",coordinates:[49.8671,40.4093]}},  {_id:"s2",tenantId:"tenant-a",storeId:"east",location:{type:"Point",coordinates:[49.8971,40.4193]}},  {_id:"s3",tenantId:"tenant-a",storeId:"south",location:{type:"Point",coordinates:[49.8571,40.3793]}}]);printjson(d.store_locations_ch20_l1.getIndexes());printjson(d.getCollectionInfos({name:"store_locations_ch20_l1"})[0].options);

The JSON Schema proves document shape, while the 2dsphere index validates that indexed geometry is usable by the geospatial index. In MongoDB 8.3, inspect 2dsphereIndexVersion:4 in index metadata. Do not hard-code that internal version into query logic; treat it as operational compatibility evidence.

3. A reversed coordinate can be valid and still be wrong

measure the semantic damage of a silent longitude/latitude reversal
from math import radians, sin, cos, asin, sqrtdef haversine_m(a,b):    lon1,lat1=map(radians,a); lon2,lat2=map(radians,b)    dlon=lon2-lon1; dlat=lat2-lat1    h=sin(dlat/2)**2+cos(lat1)*cos(lat2)*sin(dlon/2)**2    return 2*6371008.8*asin(sqrt(h))correct=(49.8671,40.4093)reversed_pair=(40.4093,49.8671)print({"distance_m": round(haversine_m(correct,reversed_pair),1)})print("Both numeric pairs are within legal longitude/latitude ranges; only application semantics reveal the reversal.")

MongoDB can reject impossible coordinates, but it cannot know that two individually legal numbers were supplied in the wrong business order. Validation therefore needs three layers: structural validation, geospatial index validation, and domain-level tests using known reference points or fixtures.

controlled failure: an actually invalid latitude
const d=db.getSiblingDB("atlasmart");try {  d.store_locations_ch20_l1.insertOne({_id:"bad",tenantId:"tenant-a",storeId:"bad-lat",location:{type:"Point",coordinates:[49.86,95]}});} catch (e) { print("expected geospatial validation failure:",e.code,e.codeName); }print("bad document count",d.store_locations_ch20_l1.countDocuments({_id:"bad"}));

4. Geometry shape rules and the 8.2 representation-precedence change

Polygon rings must close by repeating the first position as the last. GeoJSON coordinates are not arbitrary arrays: nesting depth and geometry type must agree. Large single-ring polygons also have spherical winding semantics; when your use case depends on the larger-than-hemisphere interpretation, review MongoDB's strict-winding CRS behavior instead of assuming planar polygon intuition.

Another migration boundary appeared in MongoDB 8.2. If one indexed subdocument contains both legacy numeric coordinate fields and a GeoJSON object, MongoDB 8.2+ prioritizes the GeoJSON representation regardless of field order. Earlier versions could index the first supported representation according to field order. Mixed representations are therefore a migration smell: normalize the schema and rebuild/check geospatial indexes when upgrading if old index generation depended on legacy field order.

5. Production judgment

Prefer GeoJSON plus 2dsphere for real Earth locations. Keep coordinate units and ordering explicit in API contracts, validate import pipelines, and test boundary cases such as the antimeridian, poles, polygon closure, and geometry type mismatches. Store raw source coordinates separately if you need auditability, but expose one canonical normalized geometry to queries.

Geospatial correctness is also a tenant/security concern: a coordinate filter is not authorization. Always combine spatial logic with tenant/visibility predicates and verify them in the same server-side query or aggregation. Monitor index build failures, invalid-document errors, rejected imports, unexpected empty result sets, and geographic outliers.

Bridge. Lesson 2 chooses between the spherical 2dsphere family and the planar 2d family and makes their index metadata/restrictions visible.

cleanup only this lesson lab
docker rm -f atlasmart-ch20-l1 2>/dev/null || truedocker volume rm atlasmart-ch20-l1-data 2>/dev/null || true

Check your understanding

  1. What order does MongoDB expect for longitude and latitude?
  2. Can MongoDB always detect a swapped longitude/latitude pair?
  3. What coordinate reference system do ordinary GeoJSON $geometry queries use by default?
  4. Why avoid mixing legacy numeric coordinates and GeoJSON in one indexed subdocument?
  5. Does a JSON Schema validator replace geospatial index validation?
Review the answers

1. Longitude first, latitude second.

2. No. If both values remain within valid numeric ranges, the point is valid but geographically wrong.

3. EPSG:4326/WGS84.

4. It is ambiguous and version-sensitive; MongoDB 8.2+ prioritizes GeoJSON, while older releases could depend on field order.

5. No. Schema validation checks document structure; geospatial index rules and domain-level geographic checks still matter.

Authoritative references

  • Geospatial Queries — GeoJSON versus legacy coordinates, WGS84, operators, and MongoDB 8.2 representation precedence.
  • GeoJSON Objects — supported geometry forms and longitude/latitude ordering.
  • 2dsphere Indexes — spherical indexing, sparse behavior, compound rules, and version 4 in MongoDB 8.3.
  • 2d Indexes — flat Euclidean indexing for legacy coordinate pairs and compound limitations.
  • Geospatial Index Restrictions — covered-query, collation, shard-key, supported-data, and multiple-index restrictions.
  • $geometry — EPSG:4326 default coordinate-reference behavior and GeoJSON geometry syntax.
  • $near — nearest-first query semantics and index requirements.
  • $nearSphere — spherical proximity, distance units, validation, and sorting behavior.
  • $geoWithin — containment predicates and unsorted spatial filtering.
  • $geoIntersects — intersection predicates for GeoJSON geometry.
  • $geoNear — first-stage/index rules, distanceField/key/query options, and distance units.
  • $centerSphere — spherical-cap radius semantics in radians.
  • Explain Results — executionStats interpretation and plan-format caveats.
  • MongoDB 8.3 Release Notes — 2dsphere index version 4 and current 8.3 behavior.
  • mongosh Release Notes — mongosh 2.10.0 baseline.
  • PyMongo Release Notes — PyMongo 4.17 driver baseline.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.