Added gps-summary endpoint for Map integration
This commit is contained in:
@@ -307,6 +307,15 @@ pub trait ExifDao: Sync + Send {
|
||||
limit: Option<i64>,
|
||||
offset: i64,
|
||||
) -> Result<(Vec<String>, i64), DbError>;
|
||||
|
||||
/// Get all photos with GPS coordinates
|
||||
/// Returns Vec<(file_path, latitude, longitude, date_taken)>
|
||||
fn get_all_with_gps(
|
||||
&mut self,
|
||||
context: &opentelemetry::Context,
|
||||
base_path: &str,
|
||||
recursive: bool,
|
||||
) -> Result<Vec<(String, f64, f64, Option<i64>)>, DbError>;
|
||||
}
|
||||
|
||||
pub struct SqliteExifDao {
|
||||
@@ -653,4 +662,66 @@ impl ExifDao for SqliteExifDao {
|
||||
})
|
||||
.map_err(|_| DbError::new(DbErrorKind::QueryError))
|
||||
}
|
||||
|
||||
fn get_all_with_gps(
|
||||
&mut self,
|
||||
context: &opentelemetry::Context,
|
||||
base_path: &str,
|
||||
recursive: bool,
|
||||
) -> Result<Vec<(String, f64, f64, Option<i64>)>, DbError> {
|
||||
trace_db_call(context, "query", "get_all_with_gps", |span| {
|
||||
use opentelemetry::KeyValue;
|
||||
use opentelemetry::trace::Span;
|
||||
use schema::image_exif::dsl::*;
|
||||
|
||||
span.set_attributes(vec![
|
||||
KeyValue::new("base_path", base_path.to_string()),
|
||||
KeyValue::new("recursive", recursive.to_string()),
|
||||
]);
|
||||
|
||||
let connection = &mut *self.connection.lock().unwrap();
|
||||
|
||||
// Query all photos with non-null GPS coordinates
|
||||
let mut query = image_exif
|
||||
.filter(gps_latitude.is_not_null().and(gps_longitude.is_not_null()))
|
||||
.into_boxed();
|
||||
|
||||
// Apply path filtering
|
||||
// If base_path is empty or "/", return all GPS photos (no filter)
|
||||
// Otherwise filter by path prefix
|
||||
if !base_path.is_empty() && base_path != "/" {
|
||||
// Match base path as prefix (with wildcard)
|
||||
query = query.filter(file_path.like(format!("{}%", base_path)));
|
||||
|
||||
span.set_attribute(KeyValue::new("path_filter_applied", true));
|
||||
} else {
|
||||
span.set_attribute(KeyValue::new("path_filter_applied", false));
|
||||
span.set_attribute(KeyValue::new("returning_all_gps_photos", true));
|
||||
}
|
||||
|
||||
// Load full ImageExif records
|
||||
let results: Vec<ImageExif> = query
|
||||
.load::<ImageExif>(connection)
|
||||
.map_err(|e| anyhow::anyhow!("GPS query error: {}", e))?;
|
||||
|
||||
// Convert to tuple format (path, lat, lon, date_taken)
|
||||
// Filter out any rows where GPS is still None (shouldn't happen due to filter)
|
||||
// Cast f32 GPS values to f64 for API compatibility
|
||||
let filtered: Vec<(String, f64, f64, Option<i64>)> = results
|
||||
.into_iter()
|
||||
.filter_map(|exif| {
|
||||
if let (Some(lat_val), Some(lon_val)) = (exif.gps_latitude, exif.gps_longitude) {
|
||||
Some((exif.file_path, lat_val as f64, lon_val as f64, exif.date_taken))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
span.set_attribute(KeyValue::new("result_count", filtered.len() as i64));
|
||||
|
||||
Ok(filtered)
|
||||
})
|
||||
.map_err(|_| DbError::new(DbErrorKind::QueryError))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user