Last active
October 8, 2022 03:12
-
-
Save megafarad/2f8ab04ef6dd413196c3634e49455263 to your computer and use it in GitHub Desktop.
JMdict-api Service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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