feat: Implement semantic search and smart note linking with embedding generation, vector storage, and link persistence.
This commit is contained in:
68
notes-infra/src/link_repository.rs
Normal file
68
notes-infra/src/link_repository.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use async_trait::async_trait;
|
||||
use sqlx::SqlitePool;
|
||||
use uuid::Uuid;
|
||||
|
||||
use notes_domain::entities::NoteLink;
|
||||
use notes_domain::errors::{DomainError, DomainResult};
|
||||
use notes_domain::ports::LinkRepository;
|
||||
|
||||
pub struct SqliteLinkRepository {
|
||||
pool: SqlitePool,
|
||||
}
|
||||
|
||||
impl SqliteLinkRepository {
|
||||
pub fn new(pool: SqlitePool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl LinkRepository for SqliteLinkRepository {
|
||||
async fn save_links(&self, links: &[NoteLink]) -> DomainResult<()> {
|
||||
let mut tx = self
|
||||
.pool
|
||||
.begin()
|
||||
.await
|
||||
.map_err(|e| DomainError::RepositoryError(e.to_string()))?;
|
||||
|
||||
for link in links {
|
||||
let source = link.source_note_id.to_string();
|
||||
let target = link.target_note_id.to_string();
|
||||
let created_at = link.created_at.to_rfc3339();
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO note_links (source_note_id, target_note_id, score, created_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(source_note_id, target_note_id) DO UPDATE SET
|
||||
score = excluded.score,
|
||||
created_at = excluded.created_at
|
||||
"#,
|
||||
)
|
||||
.bind(source)
|
||||
.bind(target)
|
||||
.bind(link.score)
|
||||
.bind(created_at)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| DomainError::RepositoryError(e.to_string()))?;
|
||||
}
|
||||
|
||||
tx.commit()
|
||||
.await
|
||||
.map_err(|e| DomainError::RepositoryError(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_links_for_source(&self, source_note_id: Uuid) -> DomainResult<()> {
|
||||
let source_str = source_note_id.to_string();
|
||||
sqlx::query("DELETE FROM note_links WHERE source_note_id = ?")
|
||||
.bind(source_str)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(|e| DomainError::RepositoryError(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user