Add city prefix search API using local pincode DB
All checks were successful
build-and-deploy / build-deploy (push) Successful in 35s
All checks were successful
build-and-deploy / build-deploy (push) Successful in 35s
This commit is contained in:
@@ -121,6 +121,33 @@ AUTH + SYSTEM APIS
|
|||||||
|
|
||||||
- 401 Unauthorized (missing principal / user not found)
|
- 401 Unauthorized (missing principal / user not found)
|
||||||
|
|
||||||
|
|
||||||
|
- City search API is this one:
|
||||||
|
|
||||||
|
GET /geo/cities/search
|
||||||
|
|
||||||
|
What it does:
|
||||||
|
|
||||||
|
- Searches city names by prefix from local pincode directory table.
|
||||||
|
- Returns unique city + state rows only.
|
||||||
|
- Uses local DB only (no external API call in this endpoint).
|
||||||
|
|
||||||
|
Request body:
|
||||||
|
|
||||||
|
- None.
|
||||||
|
|
||||||
|
Query params:
|
||||||
|
|
||||||
|
- q (required, minimum 2 characters)
|
||||||
|
- limit (optional, default 20, min 1, max 100)
|
||||||
|
|
||||||
|
- Allowed roles: authenticated Firebase user.
|
||||||
|
|
||||||
|
Error Codes
|
||||||
|
|
||||||
|
- 400 Bad Request (q too short)
|
||||||
|
- 401 Unauthorized
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
PROPERTY + USER APIS
|
PROPERTY + USER APIS
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.android.trisolarisserver.controller.system
|
||||||
|
|
||||||
|
import com.android.trisolarisserver.controller.common.requirePrincipal
|
||||||
|
import com.android.trisolarisserver.repo.property.IndiaPincodeCityStateRepo
|
||||||
|
import com.android.trisolarisserver.security.MyPrincipal
|
||||||
|
import org.springframework.data.domain.PageRequest
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
class GeoSearch(
|
||||||
|
private val indiaPincodeCityStateRepo: IndiaPincodeCityStateRepo
|
||||||
|
) {
|
||||||
|
@GetMapping("/geo/cities/search")
|
||||||
|
fun searchCities(
|
||||||
|
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||||
|
@RequestParam("q") q: String,
|
||||||
|
@RequestParam("limit", required = false, defaultValue = "20") limit: Int
|
||||||
|
): List<CityStateResponse> {
|
||||||
|
requirePrincipal(principal)
|
||||||
|
val query = q.trim()
|
||||||
|
if (query.length < 2) {
|
||||||
|
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "q must be at least 2 characters")
|
||||||
|
}
|
||||||
|
val boundedLimit = limit.coerceIn(1, 100)
|
||||||
|
return indiaPincodeCityStateRepo
|
||||||
|
.searchCityStateByPrefix(query, PageRequest.of(0, boundedLimit))
|
||||||
|
.map { CityStateResponse(city = it.city, state = it.state) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CityStateResponse(
|
||||||
|
val city: String,
|
||||||
|
val state: String
|
||||||
|
)
|
||||||
@@ -25,6 +25,23 @@ interface IndiaPincodeCityStateRepo : JpaRepository<IndiaPincodeCityState, UUID>
|
|||||||
@Param("pincode") pincode: Int,
|
@Param("pincode") pincode: Int,
|
||||||
pageable: Pageable
|
pageable: Pageable
|
||||||
): List<PincodeCityStateCandidate>
|
): List<PincodeCityStateCandidate>
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
select p.city as city,
|
||||||
|
p.state as state
|
||||||
|
from IndiaPincodeCityState p
|
||||||
|
where trim(p.city) <> ''
|
||||||
|
and trim(p.state) <> ''
|
||||||
|
and lower(p.city) like lower(concat(:prefix, '%'))
|
||||||
|
group by p.city, p.state
|
||||||
|
order by p.city asc, p.state asc
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun searchCityStateByPrefix(
|
||||||
|
@Param("prefix") prefix: String,
|
||||||
|
pageable: Pageable
|
||||||
|
): List<CityStateRow>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PincodeCityStateCandidate {
|
interface PincodeCityStateCandidate {
|
||||||
@@ -32,3 +49,8 @@ interface PincodeCityStateCandidate {
|
|||||||
val state: String
|
val state: String
|
||||||
val hitCount: Long
|
val hitCount: Long
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CityStateRow {
|
||||||
|
val city: String
|
||||||
|
val state: String
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user