A lexicon-driven AppView for ATProto. happyview.dev
backfill firehose jetstream atproto appview oauth lexicon
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: enable more complex database operations with `db.search()`

Trezy 8b550b5d 86660457

+47
+47
src/lua/db_api.rs
··· 87 87 })?; 88 88 db_table.set("get", get_fn)?; 89 89 90 + // db.search({ collection, field, query, limit? }) -> { records } 91 + let state_search = state.clone(); 92 + let search_fn = lua.create_async_function(move |lua, opts: mlua::Table| { 93 + let state = state_search.clone(); 94 + async move { 95 + let collection: String = opts.get("collection")?; 96 + let field: String = opts.get("field")?; 97 + let query: String = opts.get("query")?; 98 + let limit: i64 = opts.get::<i64>("limit").unwrap_or(10).min(100); 99 + 100 + let rows: Vec<(String, String, Value)> = sqlx::query_as( 101 + "SELECT uri, did, record FROM records \ 102 + WHERE collection = $1 \ 103 + AND record->>$2 ILIKE '%' || $3 || '%' \ 104 + ORDER BY \ 105 + CASE \ 106 + WHEN LOWER(record->>$2) = LOWER($3) THEN 0 \ 107 + WHEN LOWER(record->>$2) LIKE LOWER($3) || '%' THEN 1 \ 108 + ELSE 2 \ 109 + END, \ 110 + record->>$2 \ 111 + LIMIT $4", 112 + ) 113 + .bind(&collection) 114 + .bind(&field) 115 + .bind(&query) 116 + .bind(limit) 117 + .fetch_all(&state.db) 118 + .await 119 + .map_err(|e| mlua::Error::runtime(format!("DB search failed: {e}")))?; 120 + 121 + let records: Vec<Value> = rows 122 + .into_iter() 123 + .map(|(uri, _did, mut record)| { 124 + if let Some(obj) = record.as_object_mut() { 125 + obj.insert("uri".to_string(), json!(uri)); 126 + } 127 + record 128 + }) 129 + .collect(); 130 + 131 + let result = json!({ "records": records }); 132 + lua.to_value(&result) 133 + } 134 + })?; 135 + db_table.set("search", search_fn)?; 136 + 90 137 // db.count(collection, did?) -> integer 91 138 let state_count = state; 92 139 let count_fn =