Include often doesn't work - Stops call including Route for example

37 views
Skip to first unread message

Brian Runck

unread,
Jul 6, 2021, 10:18:51 AMJul 6
to MBTA Developers
I often can't get entities included even though the documentation says I should.

I'm currently defaulted to the latest API version (Jan 2021), but this problem also happened in my previous default, which was 2 versions previous, so I've never seen it work.

One example is calling the Stops API endpoint including "Route" which is accepted without 400 but never includes any routes. The documentation states (for stops):

"Relationships to include.

  • child_stops
  • connecting_stops
  • facilities
  • parent_station
  • route"
Including "route" does nothing, for example this call via the Swagger page with my API key redacted and a limit of 10 for brevity:


Not only does this not include any routes (doesn't every stop belong to one route?) but the "relationships" shows "facilities," "parent_station," and "zone" but for example, "zone" is nowhere to be found in the documentation.

What's going on here?

What's going on here?

Brian Runck

unread,
Jul 6, 2021, 10:42:44 AMJul 6
to MBTA Developers
I do see in the documentation that, for stops, "Note that route can only be included if filter[route] is present and has exactly one /data/{index}/relationships/route/data/id." For routes, "stop can only be included when filter[stop] is also specified." and it can be only ONE stop ID specified; even though you can specify multiple IDs in the filter, only one can be used to include a route in the query results.

This is unfortunate as I have to do N+1 queries to get the routes for each of the stops I care about.

Developer at MBTA

unread,
Jul 6, 2021, 11:39:48 AMJul 6
to MBTA Developers
Hi Brian,

In some cases, yes, it is currently necessary to make N+1 requests to determine the routes that serve a set of stops (an example would be displaying a "line diagram" with connecting route indicators, as mentioned here). We are looking into addressing this limitation in the future — it would be great if you could tell us more about your use case, to inform that work. In the meantime we recommend leaning on request-level caching as outlined in our Best Practices, since this data changes infrequently and "Not Modified" responses are extremely fast and don't count against your rate limit.

> (doesn't every stop belong to one route?)

Not necessarily! Stops are associated with routes via trips/schedules (since the underlying GTFS standard does not directly connect stops to routes), so if there are currently no scheduled trips that serve a stop, it would not be considered "on" any routes. Typically in this case the stop would be trimmed out of the feed entirely, but sometimes we have reason to override this.

> "zone" is nowhere to be found in the documentation.

We use this relationship to expose the value of zone_id from stops.txt in the underlying GTFS feed; "zones" do not currently exist as a separately-requestable resource.

—Developer@MBTA

Brian Runck

unread,
Jul 8, 2021, 12:25:23 PMJul 8
to MBTA Developers
One example of a use case for me is getting predictions for the closest stops, but I don't want predictions for multiple stops per route; I only want the closest stop for any given route that is in the collection of predictions returned.

Predictions gives lots of include information like route, stop, vehicle, etc. and can be filtered by long/lat and radius, but the stops endpoint can do this same filtering and sort by distance. I haven't looked at the sorting algorithm yet and I'm not sure it's exactly as accurate as I'd like, but it's pretty close in any case.

I will probably make use of caching as much as I can but when querying based on position filtering I obviously can't do that entirely.

Developer at MBTA

unread,
Jul 8, 2021, 12:48:29 PMJul 8
to MBTA Developers
Thanks for that explanation! For the specific use case you describe, it would probably be most efficient to make a single call to the /predictions endpoint and then perform the "closest stop for a given route" step on the client side. If your client is using HTTP compression (gzip), the "unwanted" predictions you end up discarding should not add too much to the request size. For the distance sorting you can use the Haversine formula, which is reasonably accurate and requires only some basic math functions. Here is the implementation the API itself uses to sort stops by distance.

—Developer@MBTA
Reply all
Reply to author
Forward
0 new messages