添加搜索功能的首选工具/插件是什么?

时间:2019-06-19 16:29:08

标签: scala playframework play-framework-2.7

我正在Scala 2.12.x,Slick 3.3.0和Playframework 2.7.x之上构建应用程序,并且需要添加Web App索引和搜索功能。目前,搜索仅针对App内的静态路由,但我可以想象,在不久的将来也必须对数据库进行索引/搜索。

有多种选择,有些像客户端插件一样简单,可以在不使用任何索引的情况下进行动态搜索。一种更可靠的方法是使用Apache Lucene ...是否有任何示例集成?插件?

还有其他值得考虑的选择吗?

1 个答案:

答案 0 :(得分:1)

scala-lucene-play-example是一个用Play演示Lucene的小例子。

路线实施:

@Singleton class ConditionsController @Inject()(
    cc: ControllerComponents,
    repo: ConditionsRepository
) extends AbstractController(cc) {

  def exact(term: String) = Action { implicit request: Request[AnyContent] =>
    Ok(Json.toJson(repo.searchByExactTitle(term)))
  }

  def fuzzy(term: String) = Action { implicit request: Request[AnyContent] =>
    Ok(Json.toJson(repo.searchByFuzzyTitle(term)))
  }

  def phrase(term: String) = Action { implicit request: Request[AnyContent] =>
    Ok(Json.toJson(repo.searchByPhraseTitle(term)))
  }

  def wildcard(term: String) = Action { implicit request: Request[AnyContent] =>
    Ok(Json.toJson(repo.searchByWildcardTitle(term)))
  }

  def fulltext(term: String) = Action { implicit request: Request[AnyContent] =>
    Ok(Json.toJson(repo.searchByFullText(term)))
  }
}

搜索逻辑

package repo

import com.outr.lucene4s._
import com.outr.lucene4s.DirectLucene
import com.outr.lucene4s.field.Field
import com.outr.lucene4s.field.value.FieldAndValue
import com.outr.lucene4s.query.{SearchResult, SearchTerm, Sort}
import javax.inject.{Inject, Singleton}

@Singleton class ConditionsRepository @Inject()(fileImporter: FileImporter) {
  private val lucene = new DirectLucene(
    uniqueFields = List("title"),
    defaultFullTextSearchable = true,
    autoCommit = true
  )
  private val title: Field[String] = lucene.create.field[String]("title")
  private val text: Field[String] = lucene.create.field[String]("text")
  initLucene()

  private def toFields(condition: Condition): Seq[FieldAndValue[_]] =
    Seq(title(condition.title.trim), text(condition.text))

  private def addToLucene(condition: Condition): Unit =
    lucene.doc().fields(toFields(condition): _*).index()

  private def initLucene(): Unit =
    fileImporter
      .asConditions()
      .foreach(addToLucene)

  private val exactTitle = title.apply _ andThen exact _
  private val fuzzyTitle = title.apply _ andThen fuzzy _
  private val phraseTitle = parseFuzzy(_ :String, Some(title))
  private val wildcardTitle = title.apply _ andThen wildcard _
  private val fulltext = lucene.fullText.apply _ andThen fuzzy _

  private def toCondition(result: SearchResult): Condition =
    Condition(result(title), result(text))

  private def search(term: String, searchFunc: String => SearchTerm): Vector[Condition] =
    lucene
      .query()
      .scoreDocs()
      .sort(Sort.Score)
      .filter(searchFunc(term.toLowerCase))
      .search()
      .pagedResultsIterator
      .toVector
      .map(toCondition)

  def searchByExactTitle(term: String): Vector[Condition] = search(term, exactTitle)
  def searchByFuzzyTitle(term: String): Vector[Condition] = search(term, fuzzyTitle)
  def searchByPhraseTitle(term: String): Vector[Condition] = search(term, phraseTitle)
  def searchByWildcardTitle(term: String): Vector[Condition] = search(term, wildcardTitle)
  def searchByFullText(term: String): Vector[Condition] = search(term, fulltext)
}

Lucene依赖

libraryDependencies += "com.outr" %% "lucene4s" % "1.8.1"