db: add queries that will be useful for the transit validation#1416
db: add queries that will be useful for the transit validation#1416tahini wants to merge 2 commits intochairemobilite:mainfrom
Conversation
There was a problem hiding this comment.
Pull Request Overview
Adds new database queries to support transit validation by fetching trips within a time window and identifying transferable nodes between paths.
- Introduces
getTripsInTimeRangeintransitSchedules.db.queries.ts - Adds
getTransferableNodePairsand its type intransitNodeTransferable.db.queries.ts - Provides test coverage for both new queries
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| packages/transition-backend/src/models/db/transitSchedules.db.queries.ts | Added getTripsInTimeRange query and export |
| packages/transition-backend/src/models/db/transitNodeTransferable.db.queries.ts | Added getTransferableNodePairs query and type |
| packages/transition-backend/src/models/db/tests/transitNodeTransferable.db.test.ts | Added tests for getTransferableNodePairs |
| packages/transition-backend/src/models/db/tests/TransitSchedule.db.test.ts | Added tests for getTripsInTimeRange |
Comments suppressed due to low confidence (1)
packages/transition-backend/src/models/db/tests/TransitSchedule.db.test.ts:1075
- No test covers the case where
lineIdsorserviceIdsarrays are empty. Adding a test for empty inputs would ensure the function handles that scenario explicitly.
describe('getTripsInTimeRange', () => {
| 'pnd.id as destination_path_id', | ||
| 'tn.*', | ||
| knex.raw( | ||
| 'ROW_NUMBER() OVER (PARTITION BY pno.id, pnd.id, tn.origin_node_id ORDER BY tn.walking_travel_time_seconds) as rn' |
There was a problem hiding this comment.
The SQL comment above shows ordering by walking_travel_distance_meters but the query orders by walking_travel_time_seconds. If the intent is to pick shortest distance transfers, update the ORDER BY clause accordingly.
| 'ROW_NUMBER() OVER (PARTITION BY pno.id, pnd.id, tn.origin_node_id ORDER BY tn.walking_travel_time_seconds) as rn' | |
| 'ROW_NUMBER() OVER (PARTITION BY pno.id, pnd.id, tn.origin_node_id ORDER BY tn.walking_travel_distance_meters) as rn' |
| .whereIn('pno.id', pathsFrom) | ||
| .whereIn('pnd.id', pathsTo); | ||
| }) | ||
| .select('*') |
There was a problem hiding this comment.
The returned objects include the SQL column rn (row number), which is not part of TransferableNodePair. Consider excluding rn in the mapping or explicitly picking only the needed fields to keep the output shape clean.
| .select('*') | |
| .select( | |
| 'origin_path_id', | |
| 'destination_path_id', | |
| 'origin_node_id', | |
| 'destination_node_id', | |
| 'walking_travel_time_seconds', | |
| 'walking_travel_distance_meters' | |
| ) |
| service1Line1.service_id = serviceId; | ||
| await dbQueries.save(service1Line1); | ||
|
|
||
| // duplicate scehdule for the same line, different service |
There was a problem hiding this comment.
Typo: scehdule should be schedule.
| // duplicate scehdule for the same line, different service | |
| // duplicate schedule for the same line, different service |
| const trips: SchedulePeriodTrip[] = []; | ||
| for (let i = 0; i < rows.length; i++) { | ||
| trips.push(scheduleTripsAttributesParser(rows[i])); | ||
| } |
There was a problem hiding this comment.
[nitpick] You can simplify converting rows to trips by using rows.map(scheduleTripsAttributesParser) instead of a manual for loop.
| const trips: SchedulePeriodTrip[] = []; | |
| for (let i = 0; i < rows.length; i++) { | |
| trips.push(scheduleTripsAttributesParser(rows[i])); | |
| } | |
| const trips = rows.map(scheduleTripsAttributesParser); |
| walking_travel_time_seconds: number; | ||
| walking_travel_distance_meters: number; | ||
| }; | ||
| const getTransferableNodePairs = async ({ |
There was a problem hiding this comment.
[nitpick] Consider validating that elements of pathsFrom and pathsTo are non-empty and valid UUIDs at the start of the function to fail fast on invalid input rather than relying on a downstream DB error.
This query returns the trips in a given time range for a list of lines and services. It is all the trips that have a departure time before the range end and an arrival time after the range start.
This query takes 2 arrays of paths: one for the unboarding nodes and another for the boarding nodes. It will find all the pairs of nodes that can transfer from one path to the other, returning the transfer travel time and distance. If many nodes are reachable from a path/node pair, it will return the one with the smallest time to reach.
greenscientist
left a comment
There was a problem hiding this comment.
Need more comments for the node transferable one.
With the comment provider in the commit message, I don't see what is the algo expected. This should go in a comment describing the function.
Do we do a path by path comparison ? (first one of one array and the first one of the other array?)
| }; | ||
|
|
||
| const getTripsInTimeRange = async ({ | ||
| rangeStart, |
There was a problem hiding this comment.
Please specifiy format as comment (epoch, time from midnight? Second, minutes?)
There was a problem hiding this comment.
Probably also add in the function comment header describing the feature that the time in the range is inclusive
| .select([`${tripTable}.*`, `${scheduleTable}.service_id`, `${scheduleTable}.line_id`]) | ||
| .join(periodTable, `${tripTable}.schedule_period_id`, `${periodTable}.id`) | ||
| .join(scheduleTable, `${periodTable}.schedule_id`, `${scheduleTable}.id`) | ||
| .whereIn(`${scheduleTable}.line_id`, lineIds) |
There was a problem hiding this comment.
Validate the performances of this query. The DB is 100% running in live tests and there may be missing indexes here... to investigate
See individual commits for details