node-GTFS
loads transit data in GTFS format, unzips it and stores it to a MongoDB database. In addition, this library provides some methods to query for agencies, routes, stops, times, fares and calendars. It also offers spatial queries to find nearby stops, routes and agencies. In addition, it can convert stops and shapes to geoJSON.
As of version 1.0.0, all node-gtfs
methods have changed to accept a query object instead of individual arguments. This allows for all fields of all GTFS files to be queried using this library. Most method names have been changed to be more general and more specific methods have been removed. For example, getRoutes
now replaces getRoutesByAgency
, getRoutesById
, getRoutesByDistance
and getRoutesByStop
.
// Old method with individual arguments, no longer supported in `node-gtfs` 1.0.0
gtfs.getRoutesByStop(agency_key, stop_id)
.then(routes => {
// do something with the array of `routes`
})
// Query in `node-gtfs` version 1.0.0
gtfs.getRoutes({
agency_key: 'caltrain',
stop_id: '123'
})
.then(routes => {
// do something with the array of `routes`
})
Additionally, as of version 0.11.0, node-gtfs
methods don't support callbacks. Use promises instead:
gtfs.getAgencies()
.then(agencies => {
// do something with the array of `agencies`
})
.catch(err => {
// handle errors here
});
Or, you use async/await:
const myAwesomeFunction = async () => {
try {
const agencies = await gtfs.getAgencies();
} catch (error) {
// handle errors here
}
}
This library has two parts: the GTFS import script and the query methods.
The GTFS-to-HTML app uses node-gtfs
for downloading, importing and querying GTFS data. It provides a good example of how to use this library.
The GTFS-to-geojson app creates geoJSON files for transit routes for use in mapping. It uses node-gtfs
for downloading, importing and querying GTFS data. It provides a good example of how to use this library.
Install node-gtfs
directly from npm:
npm install gtfs -g
Note: If you are writing a project that uses node-gtfs
then you'll want to include mongoose as a dependency with the same version that is specified in node-gtfs
package.json. Otherwise, two versions will get installed and you'll won't be able to query data that was imported.
gtfs-import [--configPath /path/to/your/custom-config.json] [--skipDelete]
const gtfs = require('gtfs');
const config = require('./config.json');
gtfs.import(config)
.then(() => {
console.log('Import Successful');
})
.catch(err => {
console.error(err);
});
Copy config-sample.json
to config.json
and then add your projects configuration to config.json
.
cp config-sample.json config.json
option | type | description |
---|---|---|
agencies |
array | An array of GTFS files to be imported. |
mongoUrl |
string | The URL of the MongoDB database to import to. |
verbose |
boolean | Whether or not to print output to the console. |
skipDelete |
boolean | Whether or not to skip deleting existing data from the database. |
Specify the GTFS files to be imported in an agencies
array. GTFS files can be imported via a url
or a local path
.
Each file needs an agency_key
, a short name you create that is specific to that GTFS file. For GTFS files that contain more than one agency, you only need to list each GTFS file once in the agencies
array, not once per agency that it contains.
To find an agency's GTFS file, visit transitfeeds.com. You can use the URL from the agency's website or you can use a URL generated from the transitfeeds.com API along with your API token.
- Specify a download URL:
{
"agencies": [
{
"agency_key": "county-connection",
"url": "http://countyconnection.com/GTFS/google_transit.zip"
}
]
}
- Specify a path to a zipped GTFS file:
{
"agencies": [
{
"agency_key": "myAgency",
"path": "/path/to/the/gtfs.zip"
}
]
}
- Specify a path to an unzipped GTFS file:
{
"agencies": [
{
"agency_key": "myAgency",
"path": "/path/to/the/unzipped/gtfs/"
}
]
}
- Exclude files - if you don't want all GTFS files to be imported, you can specify an array of files to exclude.
{
"agencies": [
{
"agency_key": "myAgency",
"path": "/path/to/the/unzipped/gtfs/",
"exclude": [
"shapes",
"stops"
]
}
]
}
- Optionally specify a proj4 projection string to correct poorly formed coordinates in the GTFS file
{
"agencies": [
{
"agency_key": "myAgency",
"path": "/path/to/the/unzipped/gtfs/",
"proj": "+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs"
}
]
}
Add the MongoDB URI to config.json
with the key mongoUrl
. Running locally, you could use something like mongodb://localhost:27017/gtfs
.
{
"mongoUrl": "mongodb://localhost:27017/gtfs",
"agencies": [
{
"agency_key": "myAgency",
"path": "/path/to/the/unzipped/gtfs/"
}
]
}
If you don't want the import script to print any output to the console, you can set verbose
to false
. Defaults to true
.
{
"mongoUrl": "mongodb://localhost:27017/gtfs",
"agencies": [
{
"agency_key": "localAgency",
"path": ""/path/to/the/unzipped/gtfs/"
}
],
"verbose": false
}
If you don't want the import script to delete all existing data from the database with the same agency_key
, you can set skipDelete
to true
. Defaults to false
.
{
"mongoUrl": "mongodb://localhost:27017/gtfs",
"agencies": [
{
"agency_key": "localAgency",
"path": ""/path/to/the/unzipped/gtfs/"
}
],
"skipDelete": true
}
The gtfs-import
script reads from a JSON configuration file and imports the GTFS files specified to a MongoDB database. Read more on setting up your configuration file.
If you want to run this locally, make sure MongoDB in installed and running.
mongod
gtfs-import
By default, it will look for a config.json
file in the project root. To specify a different path for the configuration file:
gtfs-import --configPath /path/to/your/custom-config.json
By default, the import script will delete any existing data with the same agency_key
from your database. If you don't want this to happen, pass the --skipDelete
flag
gtfs-import --skipDelete
You can specify the path to a config file to be used by the import script.
gtfs-import --configPath /path/to/your/custom-config.json
Show all command line options
gtfs-import --help
Use gtfs.import()
in your code to run an import of a GTFS file specified in a config.json file.
const gtfs = require('gtfs');
const mongoose = require('mongoose');
const config = require('config.json');
mongoose.Promise = global.Promise;
mongoose.connect(config.mongoUrl, {useMongoClient: true});
gtfs.import(config)
.then(() => {
console.log('Import Successful');
})
.catch(err => {
console.error(err);
});
Configuration can be a JSON object in your code
const gtfs = require('gtfs');
const mongoose = require('mongoose');
const config = {
mongoUrl: 'mongodb://localhost:27017/gtfs',
agencies: [
{
agency_key: 'county-connection',
url: 'http://countyconnection.com/GTFS/google_transit.zip',
exclude: [
'shapes'
]
}
]
};
mongoose.Promise = global.Promise;
mongoose.connect(config.mongoUrl, {useMongoClient: true});
gtfs.import(config)
.then(() => {
console.log('Import Successful');
})
.catch(err => {
console.error(err);
});
This library includes many methods you can use in your project to query GTFS data. These methods return promises.
For example, to get a list of all agencies within 5 miles of a specific point:
gtfs.getAgencies({
within: {
lat: 37.7749,
lon: -122.4194,
radius: 5
}
})
.then(agencies => {
// Do something with the array of `agencies`
})
.catch(err => {
// Be sure to handle errors here
});
Include this library.
var gtfs = require('gtfs');
Connect to mongo via mongoose.
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('YOUR-MONGODB-URI', {useMongoClient: true});
If you are running locally, your MongoDB uri might be something like:
mongodb://localhost:27017/gtfs
You probably want to use the same value used in your configuration JSON file for importing GTFS.
Once you have included the library and connected to your MongoDB database you can use the following methods.
Queries agencies and returns a promise. The result of the promise is an array of agencies.
// Get all agencies
gtfs.getAgencies()
.then(agencies => {
});
// Get all agencies within a a `radius` of the `lat`, `lon` specified.
// `radius` is optional and in miles. Default: 25 miles.
gtfs.getAgencies({
within: {
lat: 37.7749,
lon: -122.4194,
radius: 5
}
})
.then(agencies => {
});
// Get a specific agency
gtfs.getAgencies({
agency_key: 'caltrain'
})
.then(agencies => {
});
// Get a specific agency by `agency_name`
gtfs.getAgencies({
agency_name: 'Caltrain'
})
.then(agencies => {
});
// Get all agencies in a specific timezone
gtfs.getAgencies({
agency_timezone: 'America/Los_Angeles'
})
.then(agencies => {
});
Queries routes and returns a promise. The result of the promise is an array of routes.
// Get all routes for an agency
gtfs.getRoutes({
agency_key: 'caltrain'
})
.then(routes => {
});
// Get a specific route
gtfs.getRoutes({
agency_key: 'caltrain',
route_id: 'Lo-16APR'
})
.then(routes => {
});
// Get a few routes
const routeIds = [
'Bu-16APR',
'Lo-16APR'
]
gtfs.getRoutes({
agency_key: 'caltrain',
route_id: {
$in: routeIds
}
})
.then(routes => {
});
// Get all routes within a radius of the `lat`, `lon` specified.
// `radius` is optional and in miles. Default: 1 mile.
gtfs.getRoutes({
within: {
lat: 37.7749,
lon: -122.4194,
radius: 5
}
})
.then(routes => {
});
// Get routes that serve a specific stop.
gtfs.getRoutes({
agency_key: 'caltrain',
stop_id: '70011'
})
.then(routes => {
});
Queries stops and returns a promise. The result of the promise is an array of stops.
// Get all stops for an agency
gtfs.getStops({
agency_key: 'caltrain'
})
.then(stops => {
});
// Get a specific stop by stop_id
gtfs.getStops({
agency_key: 'caltrain',
stop_id: '70011'
})
.then(stops => {
});
// Get a few stops
const stopIds = [
'70011',
'70012'
];
gtfs.getStops({
agency_key: 'caltrain',
stop_id: {
$in: stopIds
}
})
.then(stops => {
});
// Get all stops for a specific route and direction
gtfs.getStops({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
direction_id: 1
})
.then(stops => {
});
// Get all stops within a `radius` of the `lat`, `lon` specified.
// `radius` is optional and in miles. Default: 1 mile.
gtfs.getStops({
within: {
lat: 37.7749,
lon: -122.4194,
radius: 5
}
})
.then(stops => {
});
Queries stops and returns a promise. The result of the promise is an geoJSON object of stops. All valid queries for gtfs.getStops()
work for gtfs.getStopsAsGeoJSON()
.
// Get all stops for an agency as geoJSON
gtfs.getStopsAsGeoJSON({
agency_key: 'caltrain'
})
.then(stops => {
});
// Get all stops for a specific route and direction as geoJSON
gtfs.getStopsAsGeoJSON({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
direction_id: 1
})
.then(geojson => {
});
stop_ids
is optional and can be a single stop_id
or an array of stop_ids
.
Queries stop_times and returns a promise. The result of the promise is an array of stop_times. agency_key
and stop_id
are required.
// Get all stoptimes for a specific stop
gtfs.getStoptimes({
agency_key: 'caltrain',
stop_id: '70011'
})
.then(stoptimes => {
});
// Get all stoptimes for a specific stop, route and direction
gtfs.getStoptimes({
agency_key: 'caltrain',
stop_id: '70011',
route_id: 'Lo-16APR',
direction_id: 0
})
.then(stoptimes => {
});
// Get all stoptimes for a specific stop and service_id
gtfs.getStoptimes({
agency_key: 'caltrain',
stop_id: '70011',
service_id: 'CT-16APR-Caltrain-Weekday-01'
})
.then(stoptimes => {
});
Queries trips and returns a promise. The result of the promise is an array of trips.
// Get trips for a specific route and direction
gtfs.getTrips({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
direction_id: 0
})
.then(trips => {
});
// Get trips for a specific route and direction limited by service_ids
const serviceIds = [
'CT-16APR-Caltrain-Saturday-02',
'CT-16APR-Caltrain-Sunday-02'
];
gtfs.getTrips({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
direction_id: 0,
service_id: {
$in: serviceIds
}
})
.then(trips => {
});
Queries trips and returns a promise. The result of the promise is an array of direction_ids. Useful to determine if a route has two directions or just one. agency_key
and route_id
are required.
// Find all directions for a specific route
gtfs.getDirectionsByRoute({
agency_key: 'caltrain',
route_id: 'Lo-16APR'
})
.then(directions => {
});
// Find all directions for a specific route and service_id
gtfs.getDirectionsByRoute({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
service_id: 'CT-16APR-Caltrain-Sunday-02'
})
.then(directions => {
});
Example result:
[
{
route_id: 'Bu-16APR',
trip_headsign: 'SAN FRANCISCO STATION',
direction_id: 0
},
{
route_id: 'Bu-16APR',
trip_headsign: 'DIRIDON STATION',
direction_id: 1
},
{ route_id: 'Bu-16APR',
trip_headsign: 'TAMIEN STATION',
direction_id: 1
}
];
Queries shapes and returns a promise. The result of the promise is an array of shapes sorted by shape_pt_sequence
.
// Get all shapes for an agency
gtfs.getShapes({
agency_key: 'caltrain'
})
.then(shapes => {
});
// Get all shapes for a specific route and direction
gtfs.getShapes({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
direction_id: 0
})
.then(shapes => {
});
// Get all shapes for a specific trip_id
gtfs.getShapes({
agency_key: 'caltrain',
trip_id: '37a'
})
.then(shapes => {
});
// Get all shapes for a few trip_ids
const tripIds = [
'37a',
'39a'
];
gtfs.getShapes({
agency_key: 'caltrain',
trip_id: {
$in: tripIds
}
})
.then(shapes => {
});
Queries shapes and returns a promise. The result of the promise is an geoJSON object of shapes. All valid queries for gtfs.getShapes()
work for gtfs.getShapesAsGeoJSON()
.
Returns geoJSON of shapes for the agency_key
specified.
// Get geoJSON of all routes in an agency
gtfs.getShapesAsGeoJSON({
agency_key: 'caltrain'
})
.then(geojson => {
});
// Get geoJSON of a specific route in an agency
gtfs.getShapesAsGeoJSON({
agency_key: 'caltrain',
route_id: 'Lo-16APR'
})
.then(geojson => {
});
// Get geoJSON of a specific route and direction in an agency
gtfs.getShapesAsGeoJSON({
agency_key: 'caltrain',
route_id: 'Lo-16APR',
direction_id: 0
})
.then(geojson => {
});
Queries calendars and returns a promise. The result of the promise is an array of calendars.
// Get all calendars for an agency
gtfs.getCalendars({
agency_key: 'caltrain'
})
.then(calendars => {
});
// Get calendars for an agency between two dates that apply on a Tuesday
gtfs.getCalendars({
agency_key: 'caltrain',
start_date: {$lt: 20160405},
end_date: {$gte: 20160404},
tuesday: 1
})
.then(calendars => {
});
// Get calendars for an agency by service_ids
gtfs.getCalendars({
agency_key: 'caltrain',
service_id: 'CT-16APR-Caltrain-Sunday-02'
})
.then(calendars => {
});
// Get calendars for an specific route
gtfs.getCalendars({
agency_key: 'caltrain',
route_id: 'TaSj-16APR'
})
.then(calendars => {
});
// Get calendars for several routes
gtfs.getCalendars({
agency_key: 'caltrain',
route_id: {$in: ['TaSj-16APR', 'Lo-16APR']}
})
.then(calendars => {
});
Queries feed_info and returns a promise. The result of the promise is an array of feed_infos.
// Get feed_info for a specified agency
gtfs.getFeedInfo({
agency_key: 'caltrain'
})
.then(feedInfo => {
});
Queries fare_rules and returns a promise. The result of the promise is an array of fare_rules.
// Get fare_rules for a route
gtfs.getFareRules({
agency_key: 'caltrain',
route_id: 'Lo-16APR'
})
.then(fareRules => {
});
Queries frequencies and returns a promise. The result of the promise is an array of frequencies.
// Get frequencies for a trip
gtfs.getFrequencies({
agency_key: 'caltrain',
trip_id: '1234'
})
.then(frequencies => {
});
Queries stop_attributes and returns a promise. The result of the promise is an array of stop_attributes. These are from the non-standard stop_attributes.txt
file.
// Get stop attributes for a few stops
const stopIds = [
'70011',
'70012'
];
gtfs.getStopAttributes({
agency_key: 'caltrain',
stop_id: {
$in: stopIds
}
})
.then(stopAttributes => {
});
Queries timetables and returns a promise. The result of the promise is an array of timetables. These are from the non-standard timetables.txt
file.
// Get all timetables for an agency
gtfs.getTimetables({
agency_key: 'caltrain'
})
.then(timetables => {
});
// Get a specific timetable
gtfs.getTimetables({
agency_key: 'caltrain',
timetable_id: '1'
})
.then(timetables => {
});
Queries timetable_stop_orders and returns a promise. The result of the promise is an array of timetable_stop_orders. These are from the non-standard timetable_stop_order.txt
file.
// Get timetable_stop_orders for a specific timetable
gtfs.getTimetableStopOrders({
agency_key: 'caltrain',
timetable_id: '1'
})
.then(TimetableStopOrders => {
});
Queries timetable_pages and returns a promise. The result of the promise is an array of timetable_pages. These are from the non-standard timetable_pages.txt
file.
// Get all timetable_pages for an agency
gtfs.getTimetablePages({
agency_key: 'caltrain'
})
.then(timetablePages => {
});
// Get a specific timetable_page
gtfs.getTimetablePages({
agency_key: 'caltrain',
timetable_page_id: '2'
})
.then(timetablePages => {
});
Pull requests are welcome, as is feedback and reporting issues.
To run tests:
npm test
npm run lint