forked from benetech/VideoDeduplication
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate cluster and matches enpoints (benetech#183)
- Loading branch information
1 parent
52de02b
commit bca6a0b
Showing
4 changed files
with
70 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from http import HTTPStatus | ||
|
||
from flask import jsonify, request, abort | ||
|
||
from db.access.matches import FileMatchesRequest, MatchesDAO | ||
from db.schema import Files | ||
from .blueprint import api | ||
from .helpers import parse_positive_int, Fields, parse_positive_float, parse_fields | ||
from ..model import Transform, database | ||
|
||
# Optional file fields | ||
FILE_FIELDS = Fields(Files.exif, Files.signature, Files.meta, Files.scenes) | ||
|
||
|
||
def parse_params(file): | ||
"""Parse request parameters.""" | ||
req = FileMatchesRequest(file=file) | ||
req.limit = parse_positive_int(request.args, 'limit', 20) | ||
req.offset = parse_positive_int(request.args, 'offset', 0) | ||
req.hops = parse_positive_int(request.args, 'hops', 1) | ||
req.min_distance = parse_positive_float(request.args, 'min_distance', 0.0) | ||
req.max_distance = parse_positive_float(request.args, 'max_distance', 1.0) | ||
req.preload = parse_fields(request.args, 'include', FILE_FIELDS) | ||
return req | ||
|
||
|
||
@api.route('/files/<int:file_id>/cluster', methods=['GET']) | ||
def list_file_matches(file_id): | ||
file = database.session.query(Files).get(file_id) | ||
|
||
# Handle file not found | ||
if file is None: | ||
abort(HTTPStatus.NOT_FOUND.value, f"File id not found: {file_id}") | ||
|
||
req = parse_params(file) | ||
resp = MatchesDAO.list_file_matches(req, database.session) | ||
|
||
include_flags = {field.key: True for field in req.preload} | ||
return jsonify({ | ||
'files': [Transform.file_dict(file, **include_flags) for file in resp.files], | ||
'matches': [Transform.match_dict(match) for match in resp.matches], | ||
'total': resp.total, | ||
'hops': req.hops, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,46 @@ | ||
from http import HTTPStatus | ||
|
||
from flask import jsonify, request, abort | ||
from sqlalchemy.orm import joinedload | ||
|
||
from db.access.matches import FileMatchesRequest, MatchesDAO | ||
from db.schema import Files | ||
from db.access.files import FilesDAO | ||
from db.schema import Matches, Files | ||
from .blueprint import api | ||
from .helpers import parse_positive_int, Fields, parse_positive_float, parse_fields | ||
from .helpers import parse_positive_int, Fields, parse_fields | ||
from ..model import Transform, database | ||
|
||
# Optional file fields | ||
FILE_FIELDS = Fields(Files.exif, Files.signature, Files.meta, Files.scenes) | ||
|
||
|
||
def parse_params(file): | ||
"""Parse request parameters.""" | ||
req = FileMatchesRequest(file=file) | ||
req.limit = parse_positive_int(request.args, 'limit', 20) | ||
req.offset = parse_positive_int(request.args, 'offset', 0) | ||
req.hops = parse_positive_int(request.args, 'hops', 1) | ||
req.min_distance = parse_positive_float(request.args, 'min_distance', 0.0) | ||
req.max_distance = parse_positive_float(request.args, 'max_distance', 1.0) | ||
req.preload = parse_fields(request.args, 'include', FILE_FIELDS) | ||
return req | ||
|
||
|
||
@api.route('/files/<int:file_id>/matches', methods=['GET']) | ||
def list_file_matches(file_id): | ||
limit = parse_positive_int(request.args, 'limit', 20) | ||
offset = parse_positive_int(request.args, 'offset', 0) | ||
include_fields = parse_fields(request.args, 'include', FILE_FIELDS) | ||
|
||
file = database.session.query(Files).get(file_id) | ||
|
||
# Handle file not found | ||
if file is None: | ||
abort(HTTPStatus.NOT_FOUND.value, f"File id not found: {file_id}") | ||
|
||
req = parse_params(file) | ||
resp = MatchesDAO.list_file_matches(req, database.session) | ||
query = FilesDAO.file_matches(file_id, database.session).options( | ||
joinedload(Matches.match_video_file), | ||
joinedload(Matches.query_video_file) | ||
) | ||
|
||
# Preload file fields | ||
query = FILE_FIELDS.preload(query, include_fields, Matches.match_video_file) | ||
query = FILE_FIELDS.preload(query, include_fields, Matches.query_video_file) | ||
|
||
# Get requested slice | ||
total = query.count() | ||
items = query.offset(offset).limit(limit).all() | ||
|
||
include_flags = {field.key: True for field in req.preload} | ||
include_flags = {field: True for field in include_fields} | ||
return jsonify({ | ||
'files': [Transform.file_dict(file, **include_flags) for file in resp.files], | ||
'matches': [Transform.match_dict(match) for match in resp.matches], | ||
'total': resp.total, | ||
'hops': req.hops, | ||
'items': [Transform.file_match_dict(item, file_id, **include_flags) for item in items], | ||
'total': total, | ||
'offset': offset, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters