From 1f8d65cb56c469499165d0e53dfd13d7fbf23067 Mon Sep 17 00:00:00 2001 From: DerekFurstPitt Date: Wed, 4 Feb 2026 14:58:47 -0500 Subject: [PATCH 1/5] added endpoint /entities/batch-ids/ and its corresponding neo4j query --- src/app.py | 24 +++++++++++++++++++++++- src/app_neo4j_queries.py | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/app.py b/src/app.py index d07bfaec..c4a4de35 100644 --- a/src/app.py +++ b/src/app.py @@ -95,7 +95,7 @@ # Read the secret key which may be submitted in HTTP Request Headers to override the lockout of # updates to entities with characteristics prohibiting their modification. -LOCKED_ENTITY_UPDATE_OVERRIDE_KEY = app.config['LOCKED_ENTITY_UPDATE_OVERRIDE_KEY'] +# LOCKED_ENTITY_UPDATE_OVERRIDE_KEY = app.config['LOCKED_ENTITY_UPDATE_OVERRIDE_KEY'] # Suppress InsecureRequestWarning warning when requesting status on https with ssl cert verify disabled requests.packages.urllib3.disable_warnings(category = InsecureRequestWarning) @@ -4319,6 +4319,28 @@ def entity_bulk_update(): return jsonify(list(uuids)), 202 +""" +Retrieve ids (uuid, hubmap_id) for a given id + +Parameters +---------- +id : str + The HuBMAP ID (e.g. HBM123.ABCD.456) or UUID of target entity (Dataset/Sample) + +Returns +------- +json array + Each item in the array is a json object containing the uuid and hubmap_id for the given entity. +""" +@app.route('/entities/batch-ids/', methods = ['POST']) +def get_batch_ids(): + validate_token_if_auth_header_exists(request) + require_json(request) + json_data_dict = request.get_json() + ids = app_neo4j_queries.get_batch_ids(neo4j_driver_instance, json_data_dict) + return jsonify(ids) + + #################################################################################################### ## Internal Functions #################################################################################################### diff --git a/src/app_neo4j_queries.py b/src/app_neo4j_queries.py index 2576307d..c733b592 100644 --- a/src/app_neo4j_queries.py +++ b/src/app_neo4j_queries.py @@ -1181,3 +1181,23 @@ def get_entities_by_uuid(neo4j_driver, return None return records + + +def get_batch_ids(neo4j_driver, id_list): + query = """ + MATCH (e) + WHERE e.uuid IN $id_list OR e.hubmap_id IN $id_list + WITH e, [id IN $id_list WHERE id = e.uuid OR id = e.hubmap_id][0] AS original_id + RETURN original_id, e.uuid AS uuid, e.hubmap_id AS hubmap_id + """ + + result_map = {} + + with neo4j_driver.session() as session: + result = session.run(query, id_list=id_list) + for record in result: + result_map[record['original_id']] = { + "uuid": record['uuid'], + "hubmap_id": record['hubmap_id'] + } + return result_map \ No newline at end of file From 2241fb6452cc54d50878e61369d9200345c1a354 Mon Sep 17 00:00:00 2001 From: DerekFurstPitt Date: Wed, 4 Feb 2026 15:02:58 -0500 Subject: [PATCH 2/5] added comment block describing get_batch_ids --- src/app_neo4j_queries.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/app_neo4j_queries.py b/src/app_neo4j_queries.py index c733b592..8fc130b0 100644 --- a/src/app_neo4j_queries.py +++ b/src/app_neo4j_queries.py @@ -1182,7 +1182,20 @@ def get_entities_by_uuid(neo4j_driver, return records +""" +Get the uuid and hubmap_id for each entity in a list of ids. +Parameters +---------- +neo4j_driver : neo4j.Driver object + The neo4j database connection pool +id_list : list + The list of ids + +Returns +------- +Dictionary containing the uuid and hubmap_id of each entity in the list, keyed by that entities original id given +""" def get_batch_ids(neo4j_driver, id_list): query = """ MATCH (e) From 546cd3a2192835f41e405fea396b03defd672632 Mon Sep 17 00:00:00 2001 From: DerekFurstPitt Date: Wed, 4 Feb 2026 15:05:22 -0500 Subject: [PATCH 3/5] uncommented out locked_entity_update_override_key --- src/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.py b/src/app.py index c4a4de35..27b34080 100644 --- a/src/app.py +++ b/src/app.py @@ -95,7 +95,7 @@ # Read the secret key which may be submitted in HTTP Request Headers to override the lockout of # updates to entities with characteristics prohibiting their modification. -# LOCKED_ENTITY_UPDATE_OVERRIDE_KEY = app.config['LOCKED_ENTITY_UPDATE_OVERRIDE_KEY'] +LOCKED_ENTITY_UPDATE_OVERRIDE_KEY = app.config['LOCKED_ENTITY_UPDATE_OVERRIDE_KEY'] # Suppress InsecureRequestWarning warning when requesting status on https with ssl cert verify disabled requests.packages.urllib3.disable_warnings(category = InsecureRequestWarning) From 8fea7e52670ab38f83d65e46cab6d0aee3e08dc5 Mon Sep 17 00:00:00 2001 From: DerekFurstPitt Date: Thu, 5 Feb 2026 12:30:30 -0500 Subject: [PATCH 4/5] removed trailing slash in endpoint path for batch-ids --- src/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.py b/src/app.py index 27b34080..5b36a1d0 100644 --- a/src/app.py +++ b/src/app.py @@ -4332,7 +4332,7 @@ def entity_bulk_update(): json array Each item in the array is a json object containing the uuid and hubmap_id for the given entity. """ -@app.route('/entities/batch-ids/', methods = ['POST']) +@app.route('/entities/batch-ids', methods = ['POST']) def get_batch_ids(): validate_token_if_auth_header_exists(request) require_json(request) From 25cdbf7c8bc191ad8b628bca309898d30be250a4 Mon Sep 17 00:00:00 2001 From: DerekFurstPitt Date: Fri, 6 Feb 2026 13:57:35 -0500 Subject: [PATCH 5/5] added entity spec yaml for the new batch ids endpoint. Fixed docstring to be more accurate --- entity-api-spec.yaml | 43 +++++++++++++++++++++++++++++++++++++++++++ src/app.py | 17 +++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/entity-api-spec.yaml b/entity-api-spec.yaml index f443b094..8641138b 100644 --- a/entity-api-spec.yaml +++ b/entity-api-spec.yaml @@ -3140,3 +3140,46 @@ paths: description: The given dataset is unpublished and the user does not have the authorization to view it. '500': description: Internal error + '/entities/batch-ids': + post: + summary: Retrieve the HuBMAP ID and UUID for each entity id provided in a list. + requestBody: + required: true + content: + application/json: + schema: + type: array + description: List of entity identifiers (HuBMAP IDs or UUIDs) + items: + type: string + responses: + '200': + description: Mapping of input entity identifiers to their resolved HuBMAP ID and UUID. If no items are found, will simply return empty. + content: + application/json: + schema: + type: object + additionalProperties: + type: object + properties: + hubmap_id: + type: string + description: Canonical HuBMAP ID for the entity + uuid: + type: string + format: uuid + description: UUID for the entity + required: + - hubmap_id + - uuid + examples: + batchidsexample: + value: + HBM123.ABCD.456: + hubmap_id: "HBM123.ABCD.456" + uuid: "a8098c1a-f86e-11da-bd1a-00112444be1e" + abcd1234-ef56-gh78-ij90-klmnop123456: + hubmap_id: "HBM987.WXYZ.321" + uuid: "abcd1234-ef56-gh78-ij90-klmnop123456" + '500': + description: Internal Error \ No newline at end of file diff --git a/src/app.py b/src/app.py index 5b36a1d0..ab832ddc 100644 --- a/src/app.py +++ b/src/app.py @@ -4322,15 +4322,20 @@ def entity_bulk_update(): """ Retrieve ids (uuid, hubmap_id) for a given id -Parameters ----------- -id : str - The HuBMAP ID (e.g. HBM123.ABCD.456) or UUID of target entity (Dataset/Sample) +Request Body +------------ +JSON array of entity identifiers (either uuids or HuBMAP IDs) + +Example: +[ + "HBM123.ABCD.456", + "a1234b56-c78d-90de-fg1h-23456789i01j" +] Returns ------- -json array - Each item in the array is a json object containing the uuid and hubmap_id for the given entity. +json + JSON object keyed by the entity identifier. Each value is a mapping containing the HuBMAP ID and UUID for that entity """ @app.route('/entities/batch-ids', methods = ['POST']) def get_batch_ids():