Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Feed Search endpoint is returning DB id instead of feed.stable_id for feed_references field #392

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions api/tests/test_search_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,37 @@ def test_search_feeds_filter_combine_filters_and_query(
assert result.status == status
if data_type:
assert result.data_type == data_type


def test_search_feeds_filter_reference_id(client: TestClient):
"""
Retrieve feeds combining feed ID, status, data type, and search query.
"""
params = [
("limit", 100),
("offset", 0),
("feed_id", TEST_GTFS_RT_FEED_STABLE_ID),
]
headers = {
"Authentication": "special-key",
}
response = client.request(
"GET",
"/v1/search",
headers=headers,
params=params,
)

# Assert the status code of the HTTP response
assert response.status_code == 200

# Parse the response body into a Python object
response_body = SearchFeeds200Response.parse_obj(response.json())

assert response_body.total == 1
assert len(response_body.results) == 1
assert response_body.results[0].id == TEST_GTFS_RT_FEED_STABLE_ID
assert response_body.results[0].data_type == "gtfs_rt"
assert response_body.results[0].status == "active"
assert len(response_body.results[0].feed_references) == 1
assert response_body.results[0].feed_references[0] == TEST_GTFS_FEED_STABLE_IDS[0]
19 changes: 18 additions & 1 deletion api/tests/test_utils/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,28 @@ def populate_database(db: Database):
)
for feature_id in FEATURE_IDS:
db.merge(Feature(name=feature_id), auto_commit=True)
# Need to flush the session to create the relationship between the gtfs feed and the gtfs-rt feed
db.session.flush()
db.merge(
Gtfsrealtimefeed(
id=gtfs_rt_feed_id, stable_id=TEST_GTFS_RT_FEED_STABLE_ID, data_type="gtfs_rt", status="active"
id=gtfs_rt_feed_id,
stable_id=TEST_GTFS_RT_FEED_STABLE_ID,
data_type="gtfs_rt",
status="active",
gtfs_feeds=[
Gtfsfeed(
id=gtfs_feed_ids[0],
stable_id=TEST_GTFS_FEED_STABLE_IDS[0],
data_type="gtfs",
status="active",
provider=f"{TEST_GTFS_FEED_STABLE_IDS[0]}-MobilityDataTest provider",
feed_name=f"{TEST_GTFS_FEED_STABLE_IDS[0]}-MobilityDataTest Feed Name",
)
],
),
auto_commit=True,
)

min_lat = 37.615264
max_lat = 38.2321
min_lon = -84.8984452721203
Expand Down Expand Up @@ -176,6 +192,7 @@ def populate_database(db: Database):
print(e)
finally:
# clean up the testing data regardless of the test result
db.session.execute(text("DELETE FROM feedreference"))
for dataset_id in dataset_ids:
db.session.execute(text(f"DELETE FROM notice where dataset_id ='{dataset_id}'"))
db.session.execute(text(f"DELETE FROM validationreportgtfsdataset where dataset_id ='{dataset_id}'"))
Expand Down
1 change: 1 addition & 0 deletions liquibase/changelog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
<include file="changes/feat_327.sql" relativeToChangelogFile="true"/>
<include file="changes/feat_371.sql" relativeToChangelogFile="true"/>
<include file="changes/feat_360.sql" relativeToChangelogFile="true"/>
<include file="changes/feat_389.sql" relativeToChangelogFile="true"/>
</databaseChangeLog>
97 changes: 97 additions & 0 deletions liquibase/changes/feat_389.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
-- Droping the materialized view is not possible to edit it
DROP MATERIALIZED VIEW IF EXISTS FeedSearch;

CREATE MATERIALIZED VIEW FeedSearch AS
SELECT
--feed
Feed.stable_id as feed_stable_id,
Feed.id as feed_id,
Feed.data_type,
Feed.status,
Feed.feed_name,
Feed.note,
Feed.feed_contact_email,
--source
Feed.producer_url,
Feed.authentication_info_url,
Feed.authentication_type,
Feed.api_key_parameter_name,
Feed.license_url,
Feed.provider,
--latest_dataset
Latest_dataset.id as latest_dataset_id,
Latest_dataset.hosted_url as latest_dataset_hosted_url,
Latest_dataset.downloaded_at as latest_dataset_downloaded_at,
Latest_dataset.bounding_box as latest_dataset_bounding_box,
Latest_dataset.hash as latest_dataset_hash,
--external_ids
ExternalIdJoin.external_ids,
--redirect_ids
RedirectingIdJoin.redirect_ids,
--feed gtfs_rt references
FeedReferenceJoin.feed_reference_ids,
-- feed gtfs_rt entities
EntityTypeFeedJoin.entities,
--locations
FeedLocationJoin.locations,
--full-text searchable document
setweight(to_tsvector('english', coalesce(Feed.feed_name, '')), 'C') ||
setweight(to_tsvector('english', coalesce(Feed.provider, '')), 'C') ||
COALESCE(setweight(to_tsvector('english', coalesce((FeedLocationJoin.locations #>> '{0,country_code}'), '')), 'A'), '') ||
COALESCE(setweight(to_tsvector('english', coalesce((FeedLocationJoin.locations #>> '{0,subdivision_name}'), '')), 'A'), '') ||
COALESCE(setweight(to_tsvector('english', coalesce((FeedLocationJoin.locations #>> '{0,municipality}'), '')), 'A'), '')
AS DOCUMENT
FROM FEED
LEFT JOIN (
SELECT *
FROM gtfsdataset
WHERE latest = true
) AS Latest_dataset on Latest_dataset.feed_id = Feed.id AND Feed.data_type = 'gtfs'
LEFT JOIN (
SELECT
feed_id,
json_agg(json_build_object('external_id', associated_id, 'source', source)) AS external_ids
FROM externalid
GROUP BY feed_id
) AS ExternalIdJoin ON ExternalIdJoin.feed_id = Feed.id
LEFT JOIN(
SELECT
gtfs_rt_feed_id,
array_agg(FeedReferenceJoinInnerQuery.stable_id) as feed_reference_ids
FROM FeedReference
LEFT JOIN Feed as FeedReferenceJoinInnerQuery on FeedReferenceJoinInnerQuery.id = FeedReference.gtfs_feed_id
GROUP BY gtfs_rt_feed_id
) AS FeedReferenceJoin ON FeedReferenceJoin.gtfs_rt_feed_id = Feed.id AND Feed.data_type = 'gtfs_rt'
Comment on lines +57 to +64
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the portion of the view that I modified. cc: @Alessandro100

LEFT JOIN (
SELECT
target_id,
json_agg(json_build_object('target_id', target_id, 'comment', redirect_comment)) AS redirect_ids
FROM RedirectingId
GROUP BY target_id
) AS RedirectingIdJoin ON RedirectingIdJoin.target_id = Feed.id
LEFT JOIN (
SELECT
LocationFeed.feed_id,
json_agg(json_build_object('country_code', country_code, 'subdivision_name',
subdivision_name, 'municipality', municipality)) AS locations
FROM Location
LEFT JOIN LocationFeed on LocationFeed.location_id = Location.id
GROUP BY LocationFeed.feed_id
) AS FeedLocationJoin ON FeedLocationJoin.feed_id = Feed.id
LEFT JOIN (
SELECT
feed_id,
array_agg(entity_name) as entities
FROM EntityTypeFeed
GROUP BY feed_id
) AS EntityTypeFeedJoin ON EntityTypeFeedJoin.feed_id = Feed.id AND Feed.data_type = 'gtfs_rt'
;

-- This index allows concurrent refresh on the materialized view avoiding table locks
CREATE UNIQUE INDEX idx_unique_feed_id ON FeedSearch(feed_id);

-- indices for feedsearch view optimization
CREATE INDEX feedsearch_document_idx ON FeedSearch USING GIN(document);
CREATE INDEX feedsearch_feed_stable_id ON FeedSearch(feed_stable_id);
CREATE INDEX feedsearch_data_type ON FeedSearch(data_type);
CREATE INDEX feedsearch_status ON FeedSearch(status);
2 changes: 1 addition & 1 deletion scripts/docker-localdb-rebuild-data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fi
if [ "$POPULATE_TEST_DATA" = true ]; then
# populate test data
$SCRIPT_PATH/populate-db-test-data.sh
printf "\n---------\Completed: populating test data.\n---------\n"
printf "\n---------\nCompleted: populating test data.\n---------\n"
fi

printf "\n---------\nSuccess: Rebuilding the database.\n---------\n"
Loading