我正在Scala 2.12.x,Slick 3.3.0和Playframework 2.7.x之上构建应用程序,并且需要添加Web App索引和搜索功能。目前,搜索仅针对App内的静态路由,但我可以想象,在不久的将来也必须对数据库进行索引/搜索。
有多种选择,有些像客户端插件一样简单,可以在不使用任何索引的情况下进行动态搜索。一种更可靠的方法是使用Apache Lucene ...是否有任何示例集成?插件?
还有其他值得考虑的选择吗?
答案 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"