WIP: improve search #1
|
@ -15,7 +15,7 @@ use actix_files::NamedFile;
|
||||||
use actix_web::{middleware, web, App, HttpResponse, HttpServer};
|
use actix_web::{middleware, web, App, HttpResponse, HttpServer};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
use rusqlite::{params, named_params, NO_PARAMS};
|
use rusqlite::{params, named_params, types::ToSqlOutput, Result};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -25,42 +25,62 @@ use serde_json::Value;
|
||||||
|
|
||||||
const DEFAULT_SIZE: usize = 25;
|
const DEFAULT_SIZE: usize = 25;
|
||||||
|
|
||||||
enum SortDir {
|
|
||||||
Asc,
|
|
||||||
Desc,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Sort {
|
|
||||||
Key(String),
|
|
||||||
Dir(SortDir),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Deserialize)]
|
#[derive(Copy, Clone, Debug, Deserialize)]
|
||||||
enum SortKey {
|
enum Key {
|
||||||
Name,
|
Name,
|
||||||
Size,
|
Size,
|
||||||
Seeds,
|
Seeders,
|
||||||
Leeches,
|
Leechers,
|
||||||
Scraped,
|
Date,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SortKey {
|
impl Default for Key {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Key {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{:?}", self)
|
let s = match &self {
|
||||||
|
Self::Name => "name",
|
||||||
|
Self::Size => "size_bytes",
|
||||||
|
Self::Seeders => "seeders",
|
||||||
|
Self::Leechers => "leechers",
|
||||||
|
Self::Date => "scraped_date",
|
||||||
|
};
|
||||||
|
write!(f, "{}", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Deserialize)]
|
#[derive(Copy, Clone, Debug, Deserialize)]
|
||||||
enum SortDir {
|
enum Direction {
|
||||||
Asc,
|
Asc,
|
||||||
Desc,
|
Desc,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SortDir {
|
impl Default for Direction {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Direction {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{:?}", self)
|
let s = match &self {
|
||||||
|
Self::Asc => "asc",
|
||||||
|
Self::Desc => "desc",
|
||||||
|
};
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Deserialize)]
|
||||||
|
struct Sort(Key, Direction);
|
||||||
|
|
||||||
|
impl fmt::Display for Sort {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let s = format!("{} {}", self.0, self.1);
|
||||||
|
write!(f, "{}", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +129,8 @@ struct SearchQuery {
|
||||||
q: String,
|
q: String,
|
||||||
page: Option<usize>,
|
page: Option<usize>,
|
||||||
size: Option<usize>,
|
size: Option<usize>,
|
||||||
sort_key: Option<SortKey>,
|
sort_key: Option<Key>,
|
||||||
sort_dir: Option<SortDir>,
|
sort_dir: Option<Direction>,
|
||||||
type_: Option<String>,
|
type_: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +156,7 @@ async fn search(
|
||||||
struct NewQuery {
|
struct NewQuery {
|
||||||
page: Option<usize>,
|
page: Option<usize>,
|
||||||
size: Option<usize>,
|
size: Option<usize>,
|
||||||
sort_key: Option<SortKey>,
|
sort: Option<Sort>,
|
||||||
sort_dir: Option<SortDir>,
|
|
||||||
type_: Option<String>,
|
type_: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,22 +189,23 @@ fn search_query(
|
||||||
}
|
}
|
||||||
|
|
||||||
let page = query.page.unwrap_or(1);
|
let page = query.page.unwrap_or(1);
|
||||||
let sort_key = query.sort_key.unwrap_or(SortKey::Name);
|
let key = query.sort_key.unwrap_or_default();
|
||||||
let sort_dir = query.sort_dir.unwrap_or(SortDir::Desc);
|
let direction = query.sort_dir.unwrap_or_default();
|
||||||
|
let sort = Sort(key, direction);
|
||||||
let size = cmp::min(100, query.size.unwrap_or(DEFAULT_SIZE));
|
let size = cmp::min(100, query.size.unwrap_or(DEFAULT_SIZE));
|
||||||
let type_ = query.type_.as_ref().map_or("torrent", String::deref);
|
let type_ = query.type_.as_ref().map_or("torrent", String::deref);
|
||||||
let offset = size * (page - 1);
|
let offset = size * (page - 1);
|
||||||
|
|
||||||
dbg!(
|
dbg!(
|
||||||
"query = {}, type = {}, page = {}, size = {}, sort_key = {:?}, sort_dir = {:?}",
|
"query = {}, type = {}, page = {}, size = {}, sort = {:?}",
|
||||||
q, type_, page, size, sort_key, sort_dir
|
q, type_, page, size, sort
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = if type_ == "file" {
|
let res = if type_ == "file" {
|
||||||
let results = torrent_file_search(conn, q, size, offset)?;
|
let results = torrent_file_search(conn, q, size, offset)?;
|
||||||
serde_json::to_value(&results).unwrap()
|
serde_json::to_value(&results).unwrap()
|
||||||
} else {
|
} else {
|
||||||
let results = torrent_search(conn, q, sort_key, sort_dir, size, offset)?;
|
let results = torrent_search(conn, q, sort, size, offset)?;
|
||||||
serde_json::to_value(&results).unwrap()
|
serde_json::to_value(&results).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,14 +219,13 @@ fn new_query(
|
||||||
|
|
||||||
let page = query.page.unwrap_or(1);
|
let page = query.page.unwrap_or(1);
|
||||||
let size = cmp::min(100, query.size.unwrap_or(DEFAULT_SIZE));
|
let size = cmp::min(100, query.size.unwrap_or(DEFAULT_SIZE));
|
||||||
let sort_key = query.sort_key.as_ref().unwrap_or(&SortKey::Name);
|
let sort = query.sort.unwrap_or_default();
|
||||||
let sort_dir = query.sort_dir.as_ref().unwrap_or(&SortDir::Desc);
|
|
||||||
let type_ = query.type_.as_ref().map_or("torrent", String::deref);
|
let type_ = query.type_.as_ref().map_or("torrent", String::deref);
|
||||||
let offset = size * (page - 1);
|
let offset = size * (page - 1);
|
||||||
|
|
||||||
dbg!(
|
dbg!(
|
||||||
"new, type = {}, page = {}, size = {}, sort_key = {:?}, sort_dir = {:?}",
|
"new, type = {}, page = {}, size = {}, sort = {:?}",
|
||||||
type_, page, size, sort_key, sort_dir
|
type_, page, size, sort
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = if type_ == "file" {
|
let res = if type_ == "file" {
|
||||||
|
@ -235,20 +254,19 @@ struct Torrent {
|
||||||
fn torrent_search(
|
fn torrent_search(
|
||||||
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
||||||
query: &str,
|
query: &str,
|
||||||
sort_key: SortKey,
|
sort: Sort,
|
||||||
sort_dir: SortDir,
|
|
||||||
size: usize,
|
size: usize,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
) -> Result<Vec<Torrent>, Error> {
|
) -> Result<Vec<Torrent>, Error> {
|
||||||
let stmt_str = format!("select * from torrents where name like '%' || :query || '%' order by :sort_key {} limit :offset, :size", sort_dir.to_string().to_lowercase());
|
let stmt_str = format!("select * from torrents where name like '%' || :query || '%' order by {} limit :offset, :size", sort);
|
||||||
let mut stmt = conn.prepare(&stmt_str)?;
|
let mut stmt = conn.prepare(&stmt_str)?;
|
||||||
let torrent_iter = stmt.query_map_named(
|
|
||||||
named_params!{
|
let torrent_iter = stmt.query_map(params![
|
||||||
":query": query.replace(" ", "%"),
|
query.replace(" ", "%"),
|
||||||
":sort_key": sort_key.to_string().to_lowercase(),
|
offset.to_string(),
|
||||||
":offset": offset.to_string(),
|
size.to_string(),
|
||||||
":size": size.to_string(),
|
],
|
||||||
},
|
|
||||||
|row| {
|
|row| {
|
||||||
let size: isize = row.get(2)?;
|
let size: isize = row.get(2)?;
|
||||||
println!("got size {:?}", size);
|
println!("got size {:?}", size);
|
||||||
|
|
|
@ -19,7 +19,7 @@ function buildSearchURL(sort_key, {state: { searchParams }) {
|
||||||
|
|
||||||
|
|
||||||
if (sort_key === searchParams.sort_key) {
|
if (sort_key === searchParams.sort_key) {
|
||||||
const sort_dir = searchParams.sort_dir === "Asc" ? "Desc" : "Asc";
|
const sort_dir = searchParams.sort_dir === "asc" ? "desc" : "asc";
|
||||||
searchParams.sort_dir = sort_dir;
|
searchParams.sort_dir = sort_dir;
|
||||||
console.log("no change in sort key from", sort_key, "so switch direction instead.")
|
console.log("no change in sort key from", sort_key, "so switch direction instead.")
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue