Add fuzzy_search_users to Db trait, PostgresDb
This commit is contained in:
parent
079e514379
commit
6050e0ead7
2 changed files with 47 additions and 0 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||||
|
CREATE INDEX trigram_index_users_on_github_login ON users USING GIN(github_login gin_trgm_ops);
|
|
@ -10,6 +10,7 @@ use time::OffsetDateTime;
|
||||||
pub trait Db: Send + Sync {
|
pub trait Db: Send + Sync {
|
||||||
async fn create_user(&self, github_login: &str, admin: bool) -> Result<UserId>;
|
async fn create_user(&self, github_login: &str, admin: bool) -> Result<UserId>;
|
||||||
async fn get_all_users(&self) -> Result<Vec<User>>;
|
async fn get_all_users(&self) -> Result<Vec<User>>;
|
||||||
|
async fn fuzzy_search_users(&self, query: &str, limit: u32) -> Result<Vec<User>>;
|
||||||
async fn get_user_by_id(&self, id: UserId) -> Result<Option<User>>;
|
async fn get_user_by_id(&self, id: UserId) -> Result<Option<User>>;
|
||||||
async fn get_users_by_ids(&self, ids: Vec<UserId>) -> Result<Vec<User>>;
|
async fn get_users_by_ids(&self, ids: Vec<UserId>) -> Result<Vec<User>>;
|
||||||
async fn get_user_by_github_login(&self, github_login: &str) -> Result<Option<User>>;
|
async fn get_user_by_github_login(&self, github_login: &str) -> Result<Option<User>>;
|
||||||
|
@ -99,6 +100,21 @@ impl Db for PostgresDb {
|
||||||
Ok(sqlx::query_as(query).fetch_all(&self.pool).await?)
|
Ok(sqlx::query_as(query).fetch_all(&self.pool).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fuzzy_search_users(&self, name_query: &str, limit: u32) -> Result<Vec<User>> {
|
||||||
|
let query = "
|
||||||
|
SELECT users.*
|
||||||
|
FROM users
|
||||||
|
WHERE github_login % $1
|
||||||
|
ORDER BY github_login <-> $1
|
||||||
|
LIMIT $2
|
||||||
|
";
|
||||||
|
Ok(sqlx::query_as(query)
|
||||||
|
.bind(name_query)
|
||||||
|
.bind(limit)
|
||||||
|
.fetch_all(&self.pool)
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, id: UserId) -> Result<Option<User>> {
|
async fn get_user_by_id(&self, id: UserId) -> Result<Option<User>> {
|
||||||
let users = self.get_users_by_ids(vec![id]).await?;
|
let users = self.get_users_by_ids(vec![id]).await?;
|
||||||
Ok(users.into_iter().next())
|
Ok(users.into_iter().next())
|
||||||
|
@ -640,6 +656,31 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_fuzzy_search_users() {
|
||||||
|
let test_db = TestDb::postgres().await;
|
||||||
|
let db = test_db.db();
|
||||||
|
for github_login in [
|
||||||
|
"nathansobo",
|
||||||
|
"nathansobot",
|
||||||
|
"nathanszabo",
|
||||||
|
"maxbrunsfeld",
|
||||||
|
"as-cii",
|
||||||
|
] {
|
||||||
|
db.create_user(github_login, false).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let results = db
|
||||||
|
.fuzzy_search_users("nathasbo", 10)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|user| user.github_login)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(results, &["nathansobo", "nathanszabo", "nathansobot"]);
|
||||||
|
}
|
||||||
|
|
||||||
pub struct TestDb {
|
pub struct TestDb {
|
||||||
pub db: Option<Arc<dyn Db>>,
|
pub db: Option<Arc<dyn Db>>,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
|
@ -749,6 +790,10 @@ pub mod tests {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fuzzy_search_users(&self, _: &str, _: u32) -> Result<Vec<User>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, id: UserId) -> Result<Option<User>> {
|
async fn get_user_by_id(&self, id: UserId) -> Result<Option<User>> {
|
||||||
Ok(self.get_users_by_ids(vec![id]).await?.into_iter().next())
|
Ok(self.get_users_by_ids(vec![id]).await?.into_iter().next())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue