lmdb: search_event()

This commit is contained in:
Mike Dilger 2023-07-22 12:18:26 +12:00
parent 6b537dc431
commit 49e7942f0b
3 changed files with 61 additions and 32 deletions

View File

@ -1,12 +1,11 @@
use crate::error::Error;
use crate::globals::GLOBALS;
use nostr_types::{Event, IdHex, PublicKeyHex};
use nostr_types::{IdHex, PublicKeyHex};
use serde::{Deserialize, Serialize};
use tokio::task::spawn_blocking;
/*
overlord:
search
process:
replace
@ -29,34 +28,6 @@ pub struct DbEvent {
}
impl DbEvent {
pub async fn search(text: &str) -> Result<Vec<Event>, Error> {
let sql = format!("SELECT raw FROM event WHERE (kind=1 OR kind=30023) AND (\
content LIKE '%{text}%' \
OR \
id IN (SELECT event FROM event_tag WHERE label IN ('t', 'subject', 'summary', 'title') AND field0 like '%{text}%') \
) \
ORDER BY created_at DESC");
let output: Result<Vec<Event>, Error> = spawn_blocking(move || {
let db = GLOBALS.db.blocking_lock();
let mut stmt = db.prepare(&sql)?;
let mut rows = stmt.query([])?;
let mut output: Vec<Event> = Vec::new();
while let Some(row) = rows.next()? {
let raw: String = row.get(0)?;
let event: Event = match serde_json::from_str(&raw) {
Ok(e) => e,
Err(_) => continue, // ignore the error, keep searching
};
output.push(event);
}
Ok(output)
})
.await?;
output
}
pub async fn insert(event: DbEvent) -> Result<(), Error> {
let sql = "INSERT OR IGNORE INTO event (id, raw, pubkey, created_at, kind, content, ots) \
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)";

View File

@ -3,7 +3,7 @@ mod minion;
use crate::comms::{
RelayJob, ToMinionMessage, ToMinionPayload, ToMinionPayloadDetail, ToOverlordMessage,
};
use crate::db::{DbEvent, DbEventRelay, DbPersonRelay, DbRelay};
use crate::db::{DbEventRelay, DbPersonRelay, DbRelay};
use crate::error::{Error, ErrorKind};
use crate::globals::{ZapState, GLOBALS};
use crate::people::People;
@ -1970,7 +1970,7 @@ impl Overlord {
let people_search_results = People::fetch(Some(&clause)).await?;
*GLOBALS.people_search_results.write() = people_search_results;
let note_search_results = DbEvent::search(&text).await?;
let note_search_results = GLOBALS.storage.search_events(&text)?;
*GLOBALS.note_search_results.write() = note_search_results;
Ok(())

View File

@ -454,6 +454,64 @@ impl Storage {
Ok(output)
}
pub fn search_events(&self, text: &str) -> Result<Vec<Event>, Error> {
let event_kinds = GLOBALS.settings.read().feed_displayable_event_kinds();
let needle = regex::escape(text.to_lowercase().as_str());
let re = regex::RegexBuilder::new(needle.as_str())
.unicode(true)
.case_insensitive(true)
.build()?;
let mut events = self.filter_events(|event| {
// Only feed displayable events please
if !event_kinds.contains(&event.kind) {
return false;
}
// Match contents
if re.is_match(event.content.as_ref()) {
return true;
}
// Match human readable tags
for tag in &event.tags {
match tag {
Tag::Hashtag { hashtag, .. } => {
if re.is_match(hashtag.as_ref()) {
return true;
}
}
Tag::Subject { subject, .. } => {
if re.is_match(subject.as_ref()) {
return true;
}
}
Tag::Title { title, .. } => {
if re.is_match(title.as_ref()) {
return true;
}
}
Tag::Other { tag, data } => {
if tag == "summary" && !data.is_empty() && re.is_match(data[0].as_ref()) {
return true;
}
}
_ => {}
}
}
false
})?;
events.sort_unstable_by(|a, b| {
// ORDER created_at desc
b.created_at.cmp(&a.created_at)
});
Ok(events)
}
// TBD: optimize this by storing better event indexes
// currently we stupidly scan every event (just to get LMDB up and running first)
pub fn fetch_contact_list(&self, pubkey: &PublicKey) -> Result<Option<Event>, Error> {