You've already forked AstralRinth
forked from didirus/AstralRinth
feat(search): Faceted search based on mod host (curse/modrinth) (#48)
This also adds a commandline argument library (gumdrop) for dealing with indices - reseting, reconfiguring, and skipping them. I don't know which library is best for this case, but gumdrop has shorter compile times and many fewer dependencies than clap, which is why I chose it.
This commit is contained in:
@@ -2,6 +2,7 @@ use super::IndexingError;
|
||||
use crate::search::UploadSearchMod;
|
||||
use log::info;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -200,7 +201,8 @@ pub async fn index_curseforge(
|
||||
date_modified: modified.to_string(),
|
||||
modified_timestamp: modified.timestamp(),
|
||||
latest_version,
|
||||
empty: std::borrow::Cow::Borrowed("{}{}{}"),
|
||||
host: Cow::Borrowed("curseforge"),
|
||||
empty: Cow::Borrowed("{}{}{}"),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ use log::info;
|
||||
use super::IndexingError;
|
||||
use crate::search::UploadSearchMod;
|
||||
use sqlx::postgres::PgPool;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingError> {
|
||||
info!("Indexing local mods!");
|
||||
@@ -71,7 +72,8 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
|
||||
date_modified: formatted,
|
||||
modified_timestamp: timestamp,
|
||||
latest_version: "".to_string(), // TODO: Info about latest version
|
||||
empty: std::borrow::Cow::Borrowed("{}{}{}"),
|
||||
host: Cow::Borrowed("modrinth"),
|
||||
empty: Cow::Borrowed("{}{}{}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,76 @@ pub async fn index_mods(pool: PgPool, settings: IndexingSettings) -> Result<(),
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn reset_indices() -> Result<(), IndexingError> {
|
||||
let address = &*dotenv::var("MEILISEARCH_ADDR")?;
|
||||
let client = Client::new(address, "");
|
||||
|
||||
client.delete_index("relevance_mods").await?;
|
||||
client.delete_index("downloads_mods").await?;
|
||||
client.delete_index("updated_mods").await?;
|
||||
client.delete_index("newest_mods").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn reconfigure_indices() -> Result<(), IndexingError> {
|
||||
let address = &*dotenv::var("MEILISEARCH_ADDR")?;
|
||||
let client = Client::new(address, "");
|
||||
|
||||
// Relevance Index
|
||||
update_index(&client, "relevance_mods", {
|
||||
let mut relevance_rules = default_rules();
|
||||
relevance_rules.push_back("desc(downloads)".to_string());
|
||||
relevance_rules.into()
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Downloads Index
|
||||
update_index(&client, "downloads_mods", {
|
||||
let mut downloads_rules = default_rules();
|
||||
downloads_rules.push_front("desc(downloads)".to_string());
|
||||
downloads_rules.into()
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Updated Index
|
||||
update_index(&client, "updated_mods", {
|
||||
let mut updated_rules = default_rules();
|
||||
updated_rules.push_front("desc(modified_timestamp)".to_string());
|
||||
updated_rules.into()
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Created Index
|
||||
update_index(&client, "newest_mods", {
|
||||
let mut newest_rules = default_rules();
|
||||
newest_rules.push_front("desc(created_timestamp)".to_string());
|
||||
newest_rules.into()
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_index<'a>(
|
||||
client: &'a Client<'a>,
|
||||
name: &'a str,
|
||||
rules: Vec<String>,
|
||||
) -> Result<Index<'a>, IndexingError> {
|
||||
let index = match client.get_index(name).await {
|
||||
Ok(index) => index,
|
||||
Err(meilisearch_sdk::errors::Error::IndexNotFound) => {
|
||||
client.create_index(name, Some("mod_id")).await?
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(IndexingError::IndexDBError(e));
|
||||
}
|
||||
};
|
||||
index
|
||||
.set_settings(&default_settings().with_ranking_rules(rules))
|
||||
.await?;
|
||||
Ok(index)
|
||||
}
|
||||
|
||||
async fn create_index<'a>(
|
||||
client: &'a Client<'a>,
|
||||
name: &'a str,
|
||||
@@ -129,7 +199,7 @@ pub async fn add_mods(mods: Vec<UploadSearchMod>) -> Result<(), IndexingError> {
|
||||
// Updated Index
|
||||
let updated_index = create_index(&client, "updated_mods", || {
|
||||
let mut updated_rules = default_rules();
|
||||
updated_rules.push_front("desc(updated)".to_string());
|
||||
updated_rules.push_front("desc(modified_timestamp)".to_string());
|
||||
updated_rules.into()
|
||||
})
|
||||
.await?;
|
||||
@@ -138,7 +208,7 @@ pub async fn add_mods(mods: Vec<UploadSearchMod>) -> Result<(), IndexingError> {
|
||||
// Created Index
|
||||
let newest_index = create_index(&client, "newest_mods", || {
|
||||
let mut newest_rules = default_rules();
|
||||
newest_rules.push_front("desc(created)".to_string());
|
||||
newest_rules.push_front("desc(created_timestamp)".to_string());
|
||||
newest_rules.into()
|
||||
})
|
||||
.await?;
|
||||
@@ -173,10 +243,9 @@ fn default_settings() -> Settings {
|
||||
"icon_url".to_string(),
|
||||
"author_url".to_string(),
|
||||
"date_created".to_string(),
|
||||
"created".to_string(),
|
||||
"date_modified".to_string(),
|
||||
"updated".to_string(),
|
||||
"latest_version".to_string(),
|
||||
"host".to_string(),
|
||||
];
|
||||
|
||||
let searchable_attributes = vec![
|
||||
@@ -194,7 +263,7 @@ fn default_settings() -> Settings {
|
||||
.with_accept_new_fields(true)
|
||||
.with_stop_words(vec![])
|
||||
.with_synonyms(HashMap::new())
|
||||
.with_attributes_for_faceting(vec![String::from("categories")])
|
||||
.with_attributes_for_faceting(vec![String::from("categories"), String::from("host")])
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
@@ -71,6 +71,8 @@ pub struct UploadSearchMod {
|
||||
/// Unix timestamp of the last major modification
|
||||
pub modified_timestamp: i64,
|
||||
|
||||
pub host: Cow<'static, str>,
|
||||
|
||||
/// Must be "{}{}{}", a hack until meilisearch supports searches
|
||||
/// with empty queries (https://github.com/meilisearch/MeiliSearch/issues/729)
|
||||
// This is a Cow to prevent unnecessary allocations for a static
|
||||
@@ -96,6 +98,9 @@ pub struct ResultSearchMod {
|
||||
/// RFC 3339 formatted modification date of the mod
|
||||
pub date_modified: String,
|
||||
pub latest_version: String,
|
||||
|
||||
/// The host of the mod: Either `modrinth` or `curseforge`
|
||||
pub host: String,
|
||||
}
|
||||
|
||||
impl Document for UploadSearchMod {
|
||||
|
||||
Reference in New Issue
Block a user