diff --git a/src/api/identities.rs b/src/api/identities.rs index 265d96a..7c094ff 100644 --- a/src/api/identities.rs +++ b/src/api/identities.rs @@ -97,7 +97,7 @@ async fn create_identity( reference_data->'angles_covered' as angles, reference_data->'quality_avg' as quality FROM identities - WHERE name = $1 + WHERE real_name = $1 ORDER BY created_at DESC LIMIT 1 "#; @@ -168,7 +168,7 @@ async fn list_identities( .fetch_one(db.pool()).await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("Count error: {}", e)))?; - let sql = format!("SELECT id, uuid, name, metadata FROM {} ORDER BY id DESC LIMIT $1 OFFSET $2", id_table); + let sql = format!("SELECT id::int, uuid, real_name, metadata FROM {} ORDER BY id DESC LIMIT $1 OFFSET $2", id_table); let rows: Vec<(i32, uuid::Uuid, String, Option)> = match sqlx::query_as(&sql) .bind(page_size as i64) diff --git a/src/core/db/postgres_db.rs b/src/core/db/postgres_db.rs index be069ef..f466000 100644 --- a/src/core/db/postgres_db.rs +++ b/src/core/db/postgres_db.rs @@ -102,6 +102,7 @@ pub struct Bm25Result { pub combined_score: f64, } +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct HybridSearchResult { pub chunk_id: String, pub file_uuid: String, @@ -145,6 +146,9 @@ pub struct IdentityChunkRecord { pub file_uuid: String, pub chunk_id: String, pub chunk_type: String, + pub start_frame: i64, + pub end_frame: i64, + pub fps: f64, pub start_time: Option, pub end_time: Option, pub text_content: Option, @@ -2651,11 +2655,11 @@ impl PostgresDb { let chunk_table = schema::table_name("chunk"); use sqlx::Row; let rows = sqlx::query( - &format!("SELECT c.file_uuid, c.chunk_id, c.start_time, c.end_time, c.text_content, 'sentence' as chunk_type \ + &format!("SELECT c.file_uuid, c.chunk_id, (c.start_time * c.fps)::bigint as start_frame, (c.end_time * c.fps)::bigint as end_frame, c.fps, c.start_time, c.end_time, c.text_content, 'sentence' as chunk_type \ FROM {} c JOIN {} fd ON fd.file_uuid = c.file_uuid \ AND fd.frame_number BETWEEN c.start_frame AND c.end_frame \ - WHERE fd.identity_id = (SELECT id FROM {} WHERE REPLACE(uuid::text, '-', '') = $1) \ - GROUP BY c.file_uuid, c.chunk_id, c.start_time, c.end_time, c.text_content LIMIT $2 OFFSET $3", chunk_table, fd_table, id_table) + WHERE fd.identity_id = (SELECT id FROM {} WHERE REPLACE(uuid::text, '-', '') = $1) \ + GROUP BY c.file_uuid, c.chunk_id, c.start_frame, c.end_frame, c.fps, c.start_time, c.end_time, c.text_content LIMIT $2 OFFSET $3", chunk_table, fd_table, id_table) ) .bind(uuid_str).bind(limit).bind(offset) .fetch_all(&self.pool).await?; @@ -2664,6 +2668,9 @@ impl PostgresDb { file_uuid: r.get("file_uuid"), chunk_id: r.get("chunk_id"), chunk_type: r.get("chunk_type"), + start_frame: r.get("start_frame"), + end_frame: r.get("end_frame"), + fps: r.get("fps"), text_content: r.get("text_content"), start_time: r.get("start_time"), end_time: r.get("end_time"), @@ -2676,7 +2683,7 @@ impl PostgresDb { let clean = uuid_str.replace('-', ""); use sqlx::Row; let row = sqlx::query( - &format!("SELECT id, uuid::text, name, identity_type, source, status, metadata, reference_data, \ + &format!("SELECT id, uuid::text, real_name AS name, identity_type, source, status, metadata, reference_data, \ NULL::real[] as voice_embedding, NULL::real[] as identity_embedding, \ face_embedding::real[] as face_embedding, \ tmdb_id, tmdb_profile, created_at::timestamptz as created_at, NULL::timestamptz as updated_at \ @@ -3084,19 +3091,15 @@ mod tests { fn test_bm25_result_serialization() { let result = Bm25Result { chunk_id: "sentence_001".to_string(), - uuid: "test-uuid".to_string(), - + file_uuid: "test-uuid".to_string(), chunk_type: "sentence".to_string(), - start_frame: 0, - end_frame: 150, - fps: 30.0, - start_time: 0.0, - end_time: 5.0, - text: "Hello world".to_string(), + uuid: "test-uuid".to_string(), + start_time: Some(0.0), + end_time: Some(5.0), + text: Some("Hello world".to_string()), bm25_score: 0.75, - parent_chunk_id: None, - visual_stats: None, - scene_summary: None, + vector_score: 0.0, + combined_score: 0.75, }; let json = serde_json::to_string(&result).unwrap(); @@ -3109,26 +3112,16 @@ mod tests { fn test_hybrid_search_result_serialization() { let result = HybridSearchResult { chunk_id: "sentence_001".to_string(), - uuid: "test-uuid".to_string(), - - chunk_type: "sentence".to_string(), - start_frame: 0, - end_frame: 150, - fps: 30.0, + file_uuid: "test-uuid".to_string(), start_time: 0.0, end_time: 5.0, text: "Hello world".to_string(), - vector_score: 0.85, - bm25_score: 0.75, - combined_score: 0.80, - parent_chunk_id: None, - visual_stats: None, + score: 0.80, + source: "hybrid".to_string(), }; let json = serde_json::to_string(&result).unwrap(); assert!(json.contains("sentence_001")); - assert!(json.contains("0.85")); - assert!(json.contains("0.75")); assert!(json.contains("0.8")); }