fix: identity search - fix i.name column and simplify identity_bindings join
- search_identity_text: COALESCE(i.real_name, i.actor_name) AS identity_name - search_identities_by_text: - Removed broken identity_bindings join (table has wrong schema) - Fixed i.id type mismatch (bigint -> i32 via ::int cast) - Simplified to direct face_detections join - Added error logging for debugging - Phase 4 now 11/11 passed
This commit is contained in:
@@ -67,9 +67,9 @@ test_api "POST" "/api/v1/search/visual/stats" "{\"uuid\":\"$FILE_UUID\"}" "Visua
|
||||
test_api "POST" "/api/v1/search/visual/combination" "{\"uuid\":\"$FILE_UUID\",\"combination\":[[\"person\",1],[\"car\",1]]}" "Visual search combination"
|
||||
|
||||
echo ""
|
||||
echo "── Identity Text Search (pre-existing bug: i.name column) ──"
|
||||
test_api "GET" "/api/v1/search/identity_text?uuid=$FILE_UUID&q=Grant" "" "Identity text search (known bug)"
|
||||
test_api "GET" "/api/v1/identities/search?q=Grant" "" "Identities search (known bug)"
|
||||
echo "── Identity Text Search ──"
|
||||
test_api "GET" "/api/v1/search/identity_text?uuid=$FILE_UUID&q=Grant" "" "Identity text search "
|
||||
test_api "GET" "/api/v1/identities/search?q=Grant" "" "Identities search "
|
||||
|
||||
echo ""
|
||||
echo "── Agent Search ──"
|
||||
|
||||
@@ -863,7 +863,7 @@ async fn search_identity_text(
|
||||
|
||||
let query = format!(
|
||||
r#"SELECT c.file_uuid, c.chunk_id, c.start_time, c.end_time, c.text_content,
|
||||
fd.identity_id, i.name AS identity_name, i.source AS identity_source,
|
||||
fd.identity_id, COALESCE(i.real_name, i.actor_name) AS identity_name, i.source AS identity_source,
|
||||
fd.trace_id
|
||||
FROM {} c
|
||||
LEFT JOIN {} fd ON fd.file_uuid = c.file_uuid
|
||||
@@ -933,34 +933,35 @@ async fn search_identities_by_text(
|
||||
) -> Result<Json<IdentitySearchResponse>, StatusCode> {
|
||||
use crate::core::db::schema;
|
||||
let id_table = schema::table_name("identities");
|
||||
let ib_table = schema::table_name("identity_bindings");
|
||||
let fd_table = schema::table_name("face_detections");
|
||||
let chunk_table = schema::table_name("chunk");
|
||||
let like_q = format!("%{}%", params.q.replace('%', "%%"));
|
||||
let limit = params.limit.unwrap_or(50).min(100);
|
||||
|
||||
let query = format!(
|
||||
r#"SELECT i.id, i.name, i.source, i.tmdb_id,
|
||||
r#"SELECT i.id::int, COALESCE(i.real_name, i.actor_name) AS name, i.source, i.tmdb_id,
|
||||
fd.file_uuid, fd.trace_id,
|
||||
c.chunk_id, c.start_time, c.text_content
|
||||
FROM {} i
|
||||
JOIN {} ib ON ib.identity_id = i.id AND ib.identity_type = 'trace'
|
||||
JOIN {} fd ON fd.trace_id = ib.identity_value::int
|
||||
JOIN {} fd ON fd.identity_id = i.id
|
||||
JOIN {} c ON c.file_uuid = fd.file_uuid
|
||||
AND c.start_time <= fd.frame_number / COALESCE(c.fps, 25.0)
|
||||
AND c.end_time >= fd.frame_number / COALESCE(c.fps, 25.0)
|
||||
WHERE i.name ILIKE $1
|
||||
WHERE COALESCE(i.real_name, i.actor_name) ILIKE $1
|
||||
AND ($2::text IS NULL OR fd.file_uuid = $2)
|
||||
ORDER BY i.name, c.start_time
|
||||
ORDER BY COALESCE(i.real_name, i.actor_name), c.start_time
|
||||
LIMIT $3"#,
|
||||
id_table, ib_table, fd_table, chunk_table
|
||||
id_table, fd_table, chunk_table
|
||||
);
|
||||
|
||||
let rows = sqlx::query_as::<_, (i32, String, Option<String>, Option<i32>, String, Option<i32>, String, f64, String)>(&query)
|
||||
.bind(&like_q).bind(¶ms.uuid).bind(limit)
|
||||
.fetch_all(state.db.pool())
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
.map_err(|e| {
|
||||
tracing::error!("[identities/search] Query failed: {}", e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})?;
|
||||
|
||||
let results: Vec<IdentitySearchHit> = rows
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user