diff --git a/Cargo.lock b/Cargo.lock index 1e72119..f106f1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -891,7 +891,7 @@ dependencies = [ [[package]] name = "nostr-relay" -version = "1.0.0" +version = "1.0.1" dependencies = [ "anyhow", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index e698145..e94520b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nostr-relay" -version = "1.0.0" +version = "1.0.1" edition = "2024" [dependencies] diff --git a/src/database.rs b/src/database.rs index 1208d35..2656331 100644 --- a/src/database.rs +++ b/src/database.rs @@ -28,6 +28,14 @@ pub async fn init_database(pool: &SqlitePool) -> Result<()> { d_tag TEXT, deleted_at INTEGER DEFAULT (unixepoch()) ); + + CREATE TABLE IF NOT EXISTS event_tags ( + event_id TEXT NOT NULL, + tag_name TEXT NOT NULL, + tag_value TEXT NOT NULL, + created_at INTEGER NOT NULL, + FOREIGN KEY(event_id) REFERENCES events(id) ON DELETE CASCADE + ); "#; let create_indexes = vec![ @@ -39,6 +47,7 @@ pub async fn init_database(pool: &SqlitePool) -> Result<()> { "CREATE INDEX IF NOT EXISTS idx_events_pubkey_kind_d_tag ON events(pubkey, kind, d_tag);", "CREATE INDEX IF NOT EXISTS idx_deleted_events_pubkey ON deleted_events(pubkey, event_id);", "CREATE INDEX IF NOT EXISTS idx_deleted_events_kind_d_tag ON deleted_events(kind, pubkey, d_tag);", + "CREATE INDEX IF NOT EXISTS idx_event_tags_name_value_created ON event_tags(tag_name, tag_value, created_at DESC);", ]; query(create_events_table).execute(pool).await?; diff --git a/src/nostr/event.rs b/src/nostr/event.rs index d9d49b3..57f2940 100644 --- a/src/nostr/event.rs +++ b/src/nostr/event.rs @@ -182,6 +182,7 @@ impl NostrEventExt for NostrEvent { // 保存事件到数据库,并处理可替换事件和删除事件 async fn save(&self, pool: &SqlitePool) -> Result<(), anyhow::Error> { let tags_json = serde_json::to_string(&self.tags).unwrap(); + let mut tx = pool.begin().await?; // 提取 d_tag let d_tag = self @@ -206,7 +207,7 @@ impl NostrEventExt for NostrEvent { sqlx::query("DELETE FROM events WHERE id = ? AND pubkey = ?") .bind(event_id_to_delete) .bind(&self.pubkey) - .execute(pool) + .execute(&mut *tx) .await?; if result.rows_affected() > 0 { info!( @@ -219,7 +220,7 @@ impl NostrEventExt for NostrEvent { .bind(event_id_to_delete) .bind(&self.pubkey) .bind(self.created_at as i64) - .execute(pool) + .execute(&mut *tx) .await?; if result.rows_affected() > 0 { info!( @@ -252,7 +253,7 @@ impl NostrEventExt for NostrEvent { .bind(&self.pubkey) .bind(tag_d_vector[2]) .bind(self.created_at as i64) - .execute(pool) + .execute(&mut *tx) .await?; if result.rows_affected() > 0 { info!( @@ -266,7 +267,7 @@ impl NostrEventExt for NostrEvent { .bind(&self.pubkey) .bind(tag_d_vector[2]) .bind(self.created_at as i64) - .execute(pool) + .execute(&mut *tx) .await?; if result.rows_affected() > 0 { info!( @@ -303,7 +304,7 @@ impl NostrEventExt for NostrEvent { .bind(&self.pubkey) .bind(self.kind) .bind(self.created_at as i64) - .fetch_optional(pool) + .fetch_optional(&mut *tx) .await?; if is_deleted.is_some() { @@ -313,7 +314,7 @@ impl NostrEventExt for NostrEvent { let created_at: Option = sqlx::query_scalar(sql) .bind(&self.pubkey) .bind(self.kind) - .fetch_optional(pool) + .fetch_optional(&mut *tx) .await?; if let Some(prev_created_at) = created_at { @@ -322,7 +323,7 @@ impl NostrEventExt for NostrEvent { sqlx::query(sql) .bind(&self.pubkey) .bind(self.kind) - .execute(pool) + .execute(&mut *tx) .await?; debug!( "Deleted previous replaceable event for pubkey: {}, kind: {}", @@ -351,7 +352,7 @@ impl NostrEventExt for NostrEvent { .bind(self.kind) .bind(&d_tag) .bind(self.created_at as i64) - .fetch_optional(pool) + .fetch_optional(&mut *tx) .await?; if let Some(_) = result { debug!( @@ -365,7 +366,7 @@ impl NostrEventExt for NostrEvent { .bind(&self.pubkey) .bind(self.kind) .bind(&d_tag) - .fetch_optional(pool) + .fetch_optional(&mut *tx) .await?; if let Some(prev_created_at) = created_at { @@ -375,7 +376,7 @@ impl NostrEventExt for NostrEvent { .bind(&self.pubkey) .bind(self.kind) .bind(&d_tag) - .execute(pool) + .execute(&mut *tx) .await?; debug!( "Deleted previous parameterized replaceable event for pubkey: {}, kind: {}, d_tag: {}", @@ -401,7 +402,7 @@ impl NostrEventExt for NostrEvent { sqlx::query("SELECT * FROM deleted_events WHERE event_id = ? AND pubkey = ?") .bind(&self.id) .bind(&self.pubkey) - .fetch_optional(pool) + .fetch_optional(&mut *tx) .await?; if let Some(_) = result { debug!( @@ -420,10 +421,26 @@ impl NostrEventExt for NostrEvent { .bind(&self.content) .bind(&self.sig) .bind(&d_tag) - .execute(pool) + .execute(&mut *tx) .await?; - return Ok(()); + + for tag in &self.tags { + if tag.len() >= 2 { + let tag_name = &tag[0]; + let tag_value = &tag[1]; + if tag_name.len() == 1 { + sqlx::query("INSERT INTO event_tags (event_id, tag_name, tag_value, created_at) VALUES (?, ?, ?, ?)") + .bind(&self.id) + .bind(tag_name) + .bind(tag_value) + .bind(self.created_at as i64) + .execute(&mut *tx) + .await?; + } + } + } } + tx.commit().await?; Ok(()) } diff --git a/src/nostr/filter.rs b/src/nostr/filter.rs index 7d6d073..9268ab1 100644 --- a/src/nostr/filter.rs +++ b/src/nostr/filter.rs @@ -91,11 +91,10 @@ impl FilterExt for Filter { if tag_name.starts_with('#') && !tag_values.is_empty() { let tag_letter = &tag_name[1..]; // 提取标签字母 (e.g., 'e', 'p', 'd') - // 使用 JSON 函数查询 tags 数组 - // SELECT 1 FROM json_each(tags) AS tag_arr WHERE tag_arr.value->>0 = 'p' AND tag_arr.value->>1 IN ('...', '...') - sql.push(" AND EXISTS (SELECT 1 FROM json_each(tags) AS tag_arr WHERE json_array_length(tag_arr.value) > 1 AND json_extract(tag_arr.value, '$[0]') = "); + // 使用 event_tags 表查询 + sql.push(" AND EXISTS (SELECT 1 FROM event_tags WHERE event_id = events.id AND tag_name = "); sql.push_bind(tag_letter); - sql.push(" AND json_extract(tag_arr.value, '$[1]') IN ("); + sql.push(" AND tag_value IN ("); let mut separated = sql.separated(","); for value in tag_values { separated.push_bind(value);