Fix search sorting (#5509)
* Ensure newest published versions get sorted at the top * fix issue with querying * sort by correct fields depending on server/not server project * sqlx prepare
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT v.id, v.mod_id\n FROM versions v\n WHERE mod_id = ANY($1)\n ",
|
||||
"query": "\n SELECT v.id, v.mod_id, v.date_published\n FROM versions v\n WHERE mod_id = ANY($1)\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -12,6 +12,11 @@
|
||||
"ordinal": 1,
|
||||
"name": "mod_id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "date_published",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -20,9 +25,10 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "dbdcaf9f2126e15892c28f782d4b5812d947582e3573da56e632f2b0b29fac7b"
|
||||
"hash": "7f483288e82d8c40adaed79463396e871f1a2303df9bdd4ab1b38171a8596065"
|
||||
}
|
||||
@@ -436,6 +436,9 @@ pub async fn index_local(
|
||||
created_timestamp: project.approved.timestamp(),
|
||||
date_modified: project.updated,
|
||||
modified_timestamp: project.updated.timestamp(),
|
||||
version_published_timestamp: version
|
||||
.date_published
|
||||
.timestamp(),
|
||||
license: license.clone(),
|
||||
slug: project.slug.clone(),
|
||||
// TODO
|
||||
@@ -464,31 +467,37 @@ struct PartialVersion {
|
||||
loaders: Vec<String>,
|
||||
project_types: Vec<String>,
|
||||
version_fields: Vec<QueryVersionField>,
|
||||
date_published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
async fn index_versions(
|
||||
pool: &PgPool,
|
||||
project_ids: Vec<i64>,
|
||||
) -> Result<HashMap<DBProjectId, Vec<PartialVersion>>, IndexingError> {
|
||||
let versions: HashMap<DBProjectId, Vec<DBVersionId>> = sqlx::query!(
|
||||
"
|
||||
SELECT v.id, v.mod_id
|
||||
let versions: HashMap<DBProjectId, Vec<(DBVersionId, DateTime<Utc>)>> =
|
||||
sqlx::query!(
|
||||
"
|
||||
SELECT v.id, v.mod_id, v.date_published
|
||||
FROM versions v
|
||||
WHERE mod_id = ANY($1)
|
||||
",
|
||||
&project_ids,
|
||||
)
|
||||
.fetch(pool)
|
||||
.try_fold(
|
||||
HashMap::new(),
|
||||
|mut acc: HashMap<DBProjectId, Vec<DBVersionId>>, m| {
|
||||
acc.entry(DBProjectId(m.mod_id))
|
||||
.or_default()
|
||||
.push(DBVersionId(m.id));
|
||||
async move { Ok(acc) }
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
&project_ids,
|
||||
)
|
||||
.fetch(pool)
|
||||
.try_fold(
|
||||
HashMap::new(),
|
||||
|mut acc: HashMap<
|
||||
DBProjectId,
|
||||
Vec<(DBVersionId, DateTime<Utc>)>,
|
||||
>,
|
||||
m| {
|
||||
acc.entry(DBProjectId(m.mod_id))
|
||||
.or_default()
|
||||
.push((DBVersionId(m.id), m.date_published));
|
||||
async move { Ok(acc) }
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Get project types, loaders
|
||||
#[derive(Default)]
|
||||
@@ -500,7 +509,7 @@ async fn index_versions(
|
||||
let all_version_ids = versions
|
||||
.iter()
|
||||
.flat_map(|(_, version_ids)| version_ids.iter())
|
||||
.map(|x| x.0)
|
||||
.map(|(version_id, _)| version_id.0)
|
||||
.collect::<Vec<i64>>();
|
||||
|
||||
let loaders_ptypes: DashMap<DBVersionId, VersionLoaderData> = sqlx::query!(
|
||||
@@ -567,7 +576,7 @@ async fn index_versions(
|
||||
let mut res_versions: HashMap<DBProjectId, Vec<PartialVersion>> =
|
||||
HashMap::new();
|
||||
for (project_id, version_ids) in &versions {
|
||||
for version_id in version_ids {
|
||||
for (version_id, date_published) in version_ids {
|
||||
// Extract version-specific data fetched
|
||||
// We use 'remove' as every version is only in the map once
|
||||
let version_loader_data = loaders_ptypes
|
||||
@@ -588,6 +597,7 @@ async fn index_versions(
|
||||
loaders: version_loader_data.loaders,
|
||||
project_types: version_loader_data.project_types,
|
||||
version_fields,
|
||||
date_published: *date_published,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,6 +629,7 @@ const DEFAULT_ATTRIBUTES_FOR_FACETING: &[&str] = &[
|
||||
"created_timestamp",
|
||||
"date_modified",
|
||||
"modified_timestamp",
|
||||
"version_published_timestamp",
|
||||
"project_id",
|
||||
"open_source",
|
||||
"color",
|
||||
@@ -656,6 +657,7 @@ const DEFAULT_SORTABLE_ATTRIBUTES: &[&str] = &[
|
||||
"follows",
|
||||
"date_created",
|
||||
"date_modified",
|
||||
"version_published_timestamp",
|
||||
"minecraft_java_server.verified_plays_2w",
|
||||
"minecraft_java_server.ping.data.players_online",
|
||||
];
|
||||
|
||||
@@ -209,6 +209,8 @@ pub struct UploadSearchProject {
|
||||
pub date_modified: DateTime<Utc>,
|
||||
/// Unix timestamp of the last major modification
|
||||
pub modified_timestamp: i64,
|
||||
/// Unix timestamp of the publication date of the version
|
||||
pub version_published_timestamp: i64,
|
||||
pub open_source: bool,
|
||||
pub color: Option<u32>,
|
||||
|
||||
@@ -266,30 +268,58 @@ pub struct ResultSearchProject {
|
||||
pub fn get_sort_index(
|
||||
config: &SearchConfig,
|
||||
index: &str,
|
||||
new_filters: Option<&str>,
|
||||
) -> Result<(String, &'static [&'static str]), SearchError> {
|
||||
let projects_name = config.get_index_name("projects", false);
|
||||
let projects_filtered_name =
|
||||
config.get_index_name("projects_filtered", false);
|
||||
|
||||
// TODO: this is a dumb hack, the frontend should pass the project type it's filtering directly
|
||||
let is_server = new_filters
|
||||
.is_some_and(|f| f.contains("project_types = minecraft_java_server"));
|
||||
|
||||
Ok(match index {
|
||||
"relevance" => (
|
||||
projects_name,
|
||||
&[
|
||||
"minecraft_java_server.verified_plays_2w:desc",
|
||||
"minecraft_java_server.ping.data.players_online:desc",
|
||||
"downloads:desc",
|
||||
],
|
||||
if is_server {
|
||||
&[
|
||||
"minecraft_java_server.verified_plays_2w:desc",
|
||||
"minecraft_java_server.ping.data.players_online:desc",
|
||||
"version_published_timestamp:desc",
|
||||
]
|
||||
} else {
|
||||
&["downloads:desc", "version_published_timestamp:desc"]
|
||||
},
|
||||
),
|
||||
"downloads" => (
|
||||
projects_filtered_name,
|
||||
&["downloads:desc", "version_published_timestamp:desc"],
|
||||
),
|
||||
"follows" => (
|
||||
projects_name,
|
||||
&["follows:desc", "version_published_timestamp:desc"],
|
||||
),
|
||||
"updated" | "date_modified" => (
|
||||
projects_name,
|
||||
&["date_modified:desc", "version_published_timestamp:desc"],
|
||||
),
|
||||
"newest" | "date_created" => (
|
||||
projects_name,
|
||||
&["date_created:desc", "version_published_timestamp:desc"],
|
||||
),
|
||||
"downloads" => (projects_filtered_name, &["downloads:desc"]),
|
||||
"follows" => (projects_name, &["follows:desc"]),
|
||||
"updated" | "date_modified" => (projects_name, &["date_modified:desc"]),
|
||||
"newest" | "date_created" => (projects_name, &["date_created:desc"]),
|
||||
"minecraft_java_server.verified_plays_2w" => (
|
||||
projects_name,
|
||||
&["minecraft_java_server.verified_plays_2w:desc"],
|
||||
&[
|
||||
"minecraft_java_server.verified_plays_2w:desc",
|
||||
"version_published_timestamp:desc",
|
||||
],
|
||||
),
|
||||
"minecraft_java_server.ping.data.players_online" => (
|
||||
projects_name,
|
||||
&["minecraft_java_server.ping.data.players_online:desc"],
|
||||
&[
|
||||
"minecraft_java_server.ping.data.players_online:desc",
|
||||
"version_published_timestamp:desc",
|
||||
],
|
||||
),
|
||||
i => return Err(SearchError::InvalidIndex(i.to_string())),
|
||||
})
|
||||
@@ -334,7 +364,7 @@ pub async fn search_for_project(
|
||||
.parse::<usize>()?
|
||||
.min(100);
|
||||
|
||||
let sort = get_sort_index(config, index)?;
|
||||
let sort = get_sort_index(config, index, info.new_filters.as_deref())?;
|
||||
let client = config.make_loadbalanced_read_client()?;
|
||||
let meilisearch_index = client.get_index(sort.0).await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user