API with NestJS #182. Storing coordinates in PostgreSQL with Drizzle ORM

NestJS SQL

This entry is part 182 of 182 in the API with NestJS

Many applications rely on geographical data to calculate distances and track locations. PostgreSQL offers several ways to store geospatial data, each designed with different goals. In this article, we learn how to store coordinates when working with PostgreSQL and the Drizzle ORM.

Latitude and longitude

A coordinate consists of two numbers that pinpoint a location on Earth: latitude and longitude. Since the Earth is roughly spherical, degrees are used to measure coordinates.

Latitude tells us how far north or south a place is from the equator. The equator is a line that circles the Earth, dividing it into the northern and southern hemispheres.

The smallest value for for latitude is -90° and represents the South Pole. The largest value is +90° and represents the North Pole.

Longitude measures how far east or west a place is from the Prime Meridian. The Prime Meridian line divides the Earth into the eastern and western hemispheres.

The smallest value for longitude is -180° which is the farthest west. The largest value is +180° and is the farthest east.

Both latitude and longitude can also be divided into smaller units, such as minutes and seconds. For example, the Empire State Building in New York is located at:

  • 40° 44′ 54.24″ N
    • in other words, 40 degrees, 44 minutes, and 54,24 seconds north
  • 73° 59′ 8.52″ W
    • which is 73 degrees, 59 minutes, and 8.52 seconds west

Another common way to describe coordinates is in decimal format:

  • 40.7484° N
  • 73.9857° W

If no letters indicate the direction, we can assume that positive numbers mean north and east. Negative numbers, on the other hand, mean south and west. Usually, the first number is the latitude, and the second one is the longitude:

  • 40.7484, -73.9857

Storing coordinates as numbers

The most straightforward way of storing coordinates in PostgreSQL is to use two separate columns.

database-schema.ts

Above, we use the double column type to store the coordinates. Double provides better accuracy for small fractional differences than the float column type.

This approach might be enough if our application only needs to store and retrieve coordinates without performing complex geospatial operations. However, if we want to do operations such as calculating distances or finding nearby locations, we can use other data types built into PostgreSQL.

The Point data type

Another data type that comes to mind when storing coordinates is the Point. It stores coordinates representing a point in a two-dimensional space.

database-schema.ts

By default, the Drizzle ORM maps a Point to an array with two elements. If we want to use a dictionary with the and properties, we can use the mode.

database-schema.ts

The disadvantage of the Point type

Using the Point type allows us to perform various operations using PostgreSQL. For example, let’s use the operator to calculate the distance between San Francisco and New York.

Unfortunately, the above code has a significant issue. The Point data type assumes a flat 2D surface. Since it doesn’t account for the curvature of the Earth, using it for calculations can result in inaccuracies. While it might be suitable for small distances or rough estimations, it’s not enough on a global scale.

Using PostGIS

Thankfully, PostgreSQL supports more sophisticated ways of storing and operating on coordinates. To achieve this, we need the PostGIS extension.

database-schema.ts

Let’s create a migration that adds our table.

If you want to know more about migrations with the Drizzle ORM, check out API with NestJS #176. Database migrations with the Drizzle ORM

What’s important is that we need to alter it to manually enable PostGIS in our database.

0000_add-addresses-table.sql

Inserting coordinates

Let’s create a DTO that validates if the address that the user provided is valid.

address.dto.ts

Now, we can insert the address into our database.

address.service.ts

Advantages of using PostGIS

PostGIS allows us to perform a wide range of operations on our geospatial data. What’s crucial is that PostGIS takes the curvature of the Earth into account when performing calculations. It makes PostGIS much more accurate than using a simple Point type when calculating distances over large areas. Besides simple operations, PostGIS also supports more advanced functions, such as calculating the area. On top of that, PostGIS includes spatial indexes, which are specifically optimized for working with geospatial data. This, and many more, makes PostGIS the best choice when working with geographical data with PostgreSQL.

Summary

In this article, we learned how to store coordinates with PostgreSQL, Drizzle ORM, and NestJS. To do that, we compared various different approaches, such as storing coordinates as numbers, using the Poinst data type, and taking advantage of the PostGIS extension.

For very basic applications, storing coordinates as plain numbers might be appropriate. However, if we would like to do various operations on them, we should use PostGIS so that PostgreSQL can take the curvature of the Earth into account. PostGIS provides accurate distance calculations and advanced operations, making it the preferred choice for more complex applications.

Series Navigation<< API with NestJS #181. Prepared statements in PostgreSQL with Drizzle ORM
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments