Skip to content

Instantly share code, notes, and snippets.

@megafarad
Last active October 8, 2022 03:12
Show Gist options
  • Save megafarad/2f8ab04ef6dd413196c3634e49455263 to your computer and use it in GitHub Desktop.
Save megafarad/2f8ab04ef6dd413196c3634e49455263 to your computer and use it in GitHub Desktop.
JMdict-api Service
package com.megafarad.jmdictapi
import akka.actor._
import akka.http.scaladsl.Http
import com.megafarad.jmdictapi.api.SearchRoutes
import com.typesafe.scalalogging.StrictLogging
import scala.concurrent.ExecutionContextExecutor
object Main extends App with ServerConfig with StrictLogging {
implicit val system: ActorSystem = ActorSystem()
implicit val executionContext: ExecutionContextExecutor = system.dispatcher
val modules = new ModulesWiring with SearchRoutes {
override def _system: ActorSystem = system
}
val routes = modules.userRoutes
logger.info(s"Server start at : $host:$port")
Http().newServerAt(host, port).bind(routes)
}
package com.megafarad.jmdictapi.application
import com.megafarad.jmdictapi.model.Entry
import com.megafarad.jmdictapi.mongo.MongoDb
import com.typesafe.scalalogging.StrictLogging
import org.mongodb.scala.model.{Filters, Projections}
import scala.concurrent.{ExecutionContext, Future}
class SearchRepository(mongo: MongoDb)(implicit val ec: ExecutionContext) extends SearchDao with StrictLogging {
override def search(query: String): Future[Seq[Entry]] = {
val containsKanji = query.matches("([一-龯])")
val onlyKana = query.matches("^([ぁ-んァ-ン])*$")
if (containsKanji) {
for {
exactMatch <- mongo.collection.find(Filters.eq("k_ele.keb", query))
.projection(Projections.excludeId()).toFuture()
regexMatch <- mongo.collection.find(Filters.regex("k_ele.keb", query))
.projection(Projections.excludeId()).toFuture().map(_.sortBy(calculatePriority))
} yield exactMatch ++ regexMatch
} else if (onlyKana) {
for {
exactMatch <- mongo.collection.find(Filters.eq("r_ele.reb", query))
.projection(Projections.excludeId()).toFuture()
regexMatch <- mongo.collection.find(Filters.regex("r_ele.reb", query))
.projection(Projections.excludeId()).toFuture().map(_.sortBy(calculatePriority))
} yield exactMatch ++ regexMatch
} else {
mongo.collection.find(Filters.or(
Filters.eq("sense.gloss.content", query),
Filters.regex("sense.gloss.content", "^" + query + " ", "i"),
Filters.regex("sense.gloss.content", " " + query + " ", "i")
)).projection(Projections.excludeId()).toFuture().map(_.sortBy(calculatePriority))
}
}
private def calculatePriority(entry: Entry) = {
val K_ele_pri: Seq[String] = entry.k_ele.toSeq.flatten.flatMap(_.ke_pri.toSeq.flatten)
val R_ele_pri: Seq[String] = entry.r_ele.flatMap(_.re_pri.toSeq.flatten)
val K_ele_nf = K_ele_pri.find(_.startsWith("nf")).getOrElse("nf999")
val R_ele_nf = R_ele_pri.find(_.startsWith("nf")).getOrElse("nf999")
val K_ele_ichi = K_ele_pri.exists(_.startsWith("ichi"))
val R_ele_ichi = R_ele_pri.exists(_.startsWith("ichi"))
if (K_ele_nf < R_ele_nf) {
if (K_ele_ichi) {
K_ele_pri.find(_.startsWith("ichi")).getOrElse("ichi3")
} else K_ele_nf
} else {
if (R_ele_ichi) {
R_ele_pri.find(_.startsWith("ichi")).getOrElse("ichi3")
} else R_ele_nf
}
}
}
package com.megafarad.jmdictapi.api
import akka.http.scaladsl.server._
import Directives._
import akka.http.scaladsl.model.StatusCodes
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._
import com.megafarad.jmdictapi.model.EntrySerialization._
import com.megafarad.jmdictapi.application.SearchService
import com.typesafe.scalalogging.StrictLogging
import scala.util.{Failure, Success}
trait SearchRoutes extends StrictLogging {
val searchService: SearchService
def userRoutes: Route = pathPrefix("api" / "search") {
get {
path(Segment) { query: String =>
onComplete(searchService.search(query)) {
case Success(value) => complete(StatusCodes.OK, value)
case Failure(error: Throwable) =>
logger.error("Error during query", error)
complete(StatusCodes.NoContent)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment