Fix Typesense tests (#5541)

* Fix Typesense tests

* fix

* add back author

* Split project title and authors by words and index on that

* clippy
This commit is contained in:
aecsocket
2026-03-13 13:34:51 +00:00
committed by GitHub
parent cc9059fb4a
commit 991b4d8c13
8 changed files with 66 additions and 8 deletions

1
Cargo.lock generated
View File

@@ -4922,6 +4922,7 @@ dependencies = [
"eyre", "eyre",
"futures", "futures",
"futures-util", "futures-util",
"heck 0.5.0",
"hex", "hex",
"hmac", "hmac",
"hyper-rustls 0.27.7", "hyper-rustls 0.27.7",

View File

@@ -208,7 +208,7 @@ pub async fn profile_check_installed_batch(
projects.into_iter().any(|(_, pf)| { projects.into_iter().any(|(_, pf)| {
pf.metadata pf.metadata
.as_ref() .as_ref()
.map_or(false, |m| m.project_id == project_id) .is_some_and(|m| m.project_id == project_id)
}) })
} else { } else {
false false

View File

@@ -48,6 +48,7 @@ elasticsearch = { workspace = true, features = ["experimental-apis"] }
eyre = { workspace = true } eyre = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
futures-util = { workspace = true } futures-util = { workspace = true }
heck = { workspace = true }
hex = { workspace = true } hex = { workspace = true }
hmac = { workspace = true } hmac = { workspace = true }
hyper-rustls = { workspace = true } hyper-rustls = { workspace = true }

View File

@@ -136,6 +136,21 @@ impl SearchField {
path: "categories", path: "categories",
mapping: json!({ "type": "keyword" }), mapping: json!({ "type": "keyword" }),
}, },
SearchField::Name => ElasticsearchFieldSpec {
path: "name",
mapping: json!({ "type": "search_as_you_type" }),
},
SearchField::Author => ElasticsearchFieldSpec {
path: "author",
mapping: json!({
"type": "search_as_you_type",
"fields": { "keyword": { "type": "keyword" } }
}),
},
SearchField::License => ElasticsearchFieldSpec {
path: "license",
mapping: json!({ "type": "keyword" }),
},
SearchField::ProjectTypes => ElasticsearchFieldSpec { SearchField::ProjectTypes => ElasticsearchFieldSpec {
path: "project_types", path: "project_types",
mapping: json!({ "type": "keyword" }), mapping: json!({ "type": "keyword" }),

View File

@@ -557,6 +557,18 @@ impl SearchField {
path: "categories", path: "categories",
filterable: true, filterable: true,
}, },
SearchField::Name => MeilisearchFieldSpec {
path: "name",
filterable: true,
},
SearchField::Author => MeilisearchFieldSpec {
path: "author",
filterable: true,
},
SearchField::License => MeilisearchFieldSpec {
path: "license",
filterable: true,
},
SearchField::ProjectTypes => MeilisearchFieldSpec { SearchField::ProjectTypes => MeilisearchFieldSpec {
path: "project_types", path: "project_types",
filterable: true, filterable: true,

View File

@@ -105,18 +105,18 @@ impl Default for RequestConfig {
} }
fn default_query_by() -> Vec<String> { fn default_query_by() -> Vec<String> {
["name", "slug", "summary"] ["indexed_title", "slug", "summary", "indexed_author"]
.into_iter() .into_iter()
.map(str::to_string) .map(str::to_string)
.collect() .collect()
} }
fn default_query_by_weights() -> Vec<u8> { fn default_query_by_weights() -> Vec<u8> {
vec![15, 5, 2] vec![15, 5, 2, 1]
} }
fn default_prefix() -> Vec<bool> { fn default_prefix() -> Vec<bool> {
vec![true, true, false] vec![true, true, true, true]
} }
const fn default_prioritize_exact_match() -> bool { const fn default_prioritize_exact_match() -> bool {
@@ -346,6 +346,27 @@ impl SearchField {
sort: false, sort: false,
optional: true, optional: true,
}, },
SearchField::Name => TypesenseFieldSpec {
path: "name",
ty: "string",
facet: true,
sort: false,
optional: false,
},
SearchField::Author => TypesenseFieldSpec {
path: "author",
ty: "string",
facet: true,
sort: false,
optional: false,
},
SearchField::License => TypesenseFieldSpec {
path: "license",
ty: "string",
facet: true,
sort: false,
optional: true,
},
SearchField::ProjectTypes => TypesenseFieldSpec { SearchField::ProjectTypes => TypesenseFieldSpec {
path: "project_types", path: "project_types",
ty: "string[]", ty: "string[]",
@@ -468,12 +489,11 @@ impl Typesense {
fn collection_schema(name: &str) -> Value { fn collection_schema(name: &str) -> Value {
let mut fields = vec![ let mut fields = vec![
json!({"name": "name", "type": "string", "facet": false}),
json!({"name": "summary", "type": "string", "facet": false}), json!({"name": "summary", "type": "string", "facet": false}),
json!({"name": "slug", "type": "string", "facet": false}), json!({"name": "slug", "type": "string", "facet": false}),
json!({"name": "indexed_title", "type": "string", "facet": false}),
json!({"name": "indexed_author", "type": "string", "facet": false}),
json!({"name": "log_downloads", "type": "float", "sort": true}), json!({"name": "log_downloads", "type": "float", "sort": true}),
json!({"name": "author", "type": "string", "facet": true}),
json!({"name": "license", "type": "string", "facet": true}),
json!({"name": "follows", "type": "int32", "facet": true, "sort": true}), json!({"name": "follows", "type": "int32", "facet": true, "sort": true}),
json!({"name": "created_timestamp", "type": "int64", "sort": true}), json!({"name": "created_timestamp", "type": "int64", "sort": true}),
json!({"name": "modified_timestamp", "type": "int64", "sort": true}), json!({"name": "modified_timestamp", "type": "int64", "sort": true}),
@@ -487,6 +507,7 @@ impl Typesense {
json!({ json!({
"name": name, "name": name,
"enable_nested_fields": true, "enable_nested_fields": true,
"token_separators": ["-"],
"fields": fields, "fields": fields,
"default_sorting_field": "log_downloads" "default_sorting_field": "log_downloads"
}) })
@@ -596,7 +617,7 @@ impl Typesense {
}; };
let new_filters_part = let new_filters_part =
info.new_filters.as_deref().map(|f| meili_to_typesense(f)); info.new_filters.as_deref().map(meili_to_typesense);
let legacy_part = if info.new_filters.is_none() { let legacy_part = if info.new_filters.is_none() {
combined_search_filters(info).map(|f| meili_to_typesense(&f)) combined_search_filters(info).map(|f| meili_to_typesense(&f))

View File

@@ -2,6 +2,7 @@ use chrono::{DateTime, Utc};
use dashmap::DashMap; use dashmap::DashMap;
use eyre::Result; use eyre::Result;
use futures::TryStreamExt; use futures::TryStreamExt;
use heck::ToKebabCase;
use itertools::Itertools; use itertools::Itertools;
use std::collections::HashMap; use std::collections::HashMap;
use tracing::info; use tracing::info;
@@ -426,6 +427,7 @@ pub async fn index_local(
project_id: crate::models::ids::ProjectId::from(project.id) project_id: crate::models::ids::ProjectId::from(project.id)
.to_string(), .to_string(),
name: project.name.clone(), name: project.name.clone(),
indexed_title: project.name.to_kebab_case(),
summary: project.summary.clone(), summary: project.summary.clone(),
categories: categories.clone(), categories: categories.clone(),
display_categories: display_categories.clone(), display_categories: display_categories.clone(),
@@ -434,6 +436,7 @@ pub async fn index_local(
log_downloads: (project.downloads.max(1) as f64).ln(), log_downloads: (project.downloads.max(1) as f64).ln(),
icon_url: project.icon_url.clone(), icon_url: project.icon_url.clone(),
author: owner.clone(), author: owner.clone(),
indexed_author: owner.to_kebab_case(),
date_created: project.approved, date_created: project.approved,
created_timestamp: project.approved.timestamp(), created_timestamp: project.approved.timestamp(),
date_modified: project.updated, date_modified: project.updated,

View File

@@ -186,6 +186,9 @@ pub enum SearchBackendKind {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::EnumIter)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::EnumIter)]
pub enum SearchField { pub enum SearchField {
Categories, Categories,
Name,
Author,
License,
ProjectTypes, ProjectTypes,
ProjectId, ProjectId,
OpenSource, OpenSource,
@@ -225,7 +228,9 @@ pub struct UploadSearchProject {
pub project_types: Vec<String>, pub project_types: Vec<String>,
pub slug: Option<String>, pub slug: Option<String>,
pub author: String, pub author: String,
pub indexed_author: String,
pub name: String, pub name: String,
pub indexed_title: String,
pub summary: String, pub summary: String,
pub categories: Vec<String>, pub categories: Vec<String>,
pub display_categories: Vec<String>, pub display_categories: Vec<String>,