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