This commit is contained in:
Andras Schmelczer 2026-02-14 12:53:29 +00:00
parent 3a3f899ea2
commit 128b3191e7
68 changed files with 28060 additions and 1152 deletions

View file

@ -14,6 +14,8 @@ pub struct PlaceResult {
place_type: String,
lat: f32,
lon: f32,
#[serde(skip_serializing_if = "Option::is_none")]
city: Option<String>,
}
#[derive(Serialize)]
@ -24,7 +26,7 @@ pub struct PlacesResponse {
#[derive(Deserialize)]
#[allow(clippy::min_ident_chars)]
pub struct PlacesParams {
q: Option<String>,
q: String,
limit: Option<usize>,
}
@ -32,10 +34,11 @@ pub async fn get_places(
state: Arc<AppState>,
Query(params): Query<PlacesParams>,
) -> Result<Json<PlacesResponse>, (StatusCode, String)> {
let query = params
.q
.filter(|val| !val.is_empty())
.ok_or((StatusCode::BAD_REQUEST, "Missing 'q' parameter".to_string()))?;
let query = if params.q.is_empty() {
return Err((StatusCode::BAD_REQUEST, "'q' must not be empty".into()));
} else {
params.q
};
let limit = params.limit.unwrap_or(7).min(20);
@ -45,26 +48,37 @@ pub async fn get_places(
let pd = &state.place_data;
// Linear scan — ~50-100k rows, <1ms
let mut matches: Vec<(usize, bool, u8, usize)> = pd
// Tuple: (row_idx, is_exact, is_prefix, type_rank, population, name_len)
let mut matches: Vec<(usize, bool, bool, u8, u32, usize)> = pd
.name_lower
.iter()
.enumerate()
.filter_map(|(idx, name)| {
if name.contains(&query_lower) {
let is_exact = name.len() == query_lower.len();
let is_prefix = name.starts_with(&query_lower);
Some((idx, is_prefix, pd.type_rank[idx], pd.name[idx].len()))
Some((
idx,
is_exact,
is_prefix,
pd.type_rank[idx],
pd.population[idx],
pd.name[idx].len(),
))
} else {
None
}
})
.collect();
// Sort: prefix first, then by type rank (cities before hamlets), then shorter names first
// Sort: exact first, then prefix, then type rank asc, then population desc, then name length asc
matches.sort_unstable_by(|lhs, rhs| {
rhs.1
.cmp(&lhs.1)
.then(lhs.2.cmp(&rhs.2))
.then(rhs.2.cmp(&lhs.2))
.then(lhs.3.cmp(&rhs.3))
.then(rhs.4.cmp(&lhs.4))
.then(lhs.5.cmp(&rhs.5))
});
matches.truncate(limit);
@ -76,6 +90,7 @@ pub async fn get_places(
place_type: pd.place_type.get(idx).to_string(),
lat: pd.lat[idx],
lon: pd.lon[idx],
city: pd.city[idx].clone(),
})
.collect();