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:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -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",
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
@@ -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" }),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
Reference in New Issue
Block a user