diff --git a/search-api/src/main/scala/no/ndla/searchapi/integration/GrepApiClient.scala b/search-api/src/main/scala/no/ndla/searchapi/integration/GrepApiClient.scala index d13037a808..07d6202b3d 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/integration/GrepApiClient.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/integration/GrepApiClient.scala @@ -30,17 +30,20 @@ trait GrepApiClient { import props.GrepApiUrl private val GrepApiEndpoint = s"$GrepApiUrl/kl06/v201906" - private def getAllKjerneelementer: Try[List[GrepElement]] = - get[List[GrepElement]](s"$GrepApiEndpoint/kjerneelementer-lk20/").map(_.distinct) + private def getAllKjerneelementer: Try[List[GrepKjerneelement]] = + get[List[GrepKjerneelement]](s"$GrepApiEndpoint/kjerneelementer-lk20/").map(_.distinct) - private def getAllKompetansemaal: Try[List[GrepElement]] = - get[List[GrepElement]](s"$GrepApiEndpoint/kompetansemaal-lk20/").map(_.distinct) + private def getAllKompetansemaal: Try[List[GrepKompetansemaal]] = + get[List[GrepKompetansemaal]](s"$GrepApiEndpoint/kompetansemaal-lk20/").map(_.distinct) - private def getAllKompetansemaalSett: Try[List[GrepElement]] = - get[List[GrepElement]](s"$GrepApiEndpoint/kompetansemaalsett-lk20/").map(_.distinct) + private def getAllKompetansemaalSett: Try[List[GrepKompetansemaalSett]] = + get[List[GrepKompetansemaalSett]](s"$GrepApiEndpoint/kompetansemaalsett-lk20/").map(_.distinct) - private def getAllTverrfagligeTemaer: Try[List[GrepElement]] = - get[List[GrepElement]](s"$GrepApiEndpoint/tverrfaglige-temaer-lk20/").map(_.distinct) + private def getAllTverrfagligeTemaer: Try[List[GrepTverrfagligTema]] = + get[List[GrepTverrfagligTema]](s"$GrepApiEndpoint/tverrfaglige-temaer-lk20/").map(_.distinct) + + private def getAllLaereplaner: Try[List[GrepLaererplan]] = + get[List[GrepLaererplan]](s"$GrepApiEndpoint/laereplaner-lk20/").map(_.distinct) // NOTE: We add a helper so we don't have to provide `()` where this is used :^) val getGrepBundle: () => Try[GrepBundle] = () => _getGrepBundle(()) @@ -65,17 +68,20 @@ trait GrepApiClient { val kompetansemaal = tryToFuture(() => getAllKompetansemaal) val kompetansemaalsett = tryToFuture(() => getAllKompetansemaalSett) val tverrfagligeTemaer = tryToFuture(() => getAllTverrfagligeTemaer) + val laererplaner = tryToFuture(() => getAllLaereplaner) val x = for { kjerne <- kjerneelementer kompetanse <- kompetansemaal kompetansesett <- kompetansemaalsett tverrfag <- tverrfagligeTemaer + laere <- laererplaner } yield GrepBundle( kjerneelementer = kjerne, kompetansemaal = kompetanse, kompetansemaalsett = kompetansesett, - tverrfagligeTemaer = tverrfag + tverrfagligeTemaer = tverrfag, + laereplaner = laere ) Try(Await.result(x, Duration(300, "seconds"))) match { diff --git a/search-api/src/main/scala/no/ndla/searchapi/model/api/grep/GrepResultDTO.scala b/search-api/src/main/scala/no/ndla/searchapi/model/api/grep/GrepResultDTO.scala index 53a1eb945e..57ce3faea8 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/model/api/grep/GrepResultDTO.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/model/api/grep/GrepResultDTO.scala @@ -16,7 +16,8 @@ import sttp.tapir.Schema.annotations.description @description("Information about a single grep search result entry") case class GrepResultDTO( @description("The grep code") code: String, - @description("The greps title") title: TitleDTO + @description("The greps title") title: TitleDTO, + @description("The grep laereplan") laereplanCode: Option[String] ) object GrepResultDTO { diff --git a/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepBundle.scala b/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepBundle.scala index 102534d86c..dea59ad8d6 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepBundle.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepBundle.scala @@ -8,13 +8,19 @@ package no.ndla.searchapi.model.grep case class GrepBundle( - kjerneelementer: List[GrepElement], - kompetansemaal: List[GrepElement], + kjerneelementer: List[GrepKjerneelement], + kompetansemaal: List[GrepKompetansemaal], kompetansemaalsett: List[GrepElement], - tverrfagligeTemaer: List[GrepElement] + tverrfagligeTemaer: List[GrepElement], + laereplaner: List[GrepLaererplan] ) { - val grepContext: List[GrepElement] = kjerneelementer ++ kompetansemaal ++ kompetansemaalsett ++ tverrfagligeTemaer + val grepContext: List[GrepElement] = + kjerneelementer ++ + kompetansemaal ++ + kompetansemaalsett ++ + tverrfagligeTemaer ++ + laereplaner val grepContextByCode: Map[String, GrepElement] = Map.from(grepContext.map(elem => elem.kode -> elem)) diff --git a/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepElement.scala b/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepElement.scala index b5925fa89a..9ea8db7465 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepElement.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/model/grep/GrepElement.scala @@ -7,12 +7,56 @@ package no.ndla.searchapi.model.grep -import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} import io.circe.{Decoder, Encoder} +import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} + +sealed trait GrepElement { + val kode: String + val tittel: Seq[GrepTitle] +} + +sealed trait BelongsToLaerePlan { + val tilhoerer_laereplan: BelongsToObj +} + +case class GrepKjerneelement(kode: String, tittel: Seq[GrepTitle], tilhoerer_laereplan: BelongsToObj) + extends GrepElement + with BelongsToLaerePlan +object GrepKjerneelement { + implicit val encoder: Encoder[GrepKjerneelement] = deriveEncoder + implicit val decoder: Decoder[GrepKjerneelement] = deriveDecoder +} -case class GrepElement(kode: String, tittel: Seq[GrepTitle]) +case class BelongsToObj(kode: String) +object BelongsToObj { + implicit val encoder: Encoder[BelongsToObj] = deriveEncoder + implicit val decoder: Decoder[BelongsToObj] = deriveDecoder +} + +case class GrepKompetansemaal(kode: String, tittel: Seq[GrepTitle], tilhoerer_laereplan: BelongsToObj) + extends GrepElement + with BelongsToLaerePlan +object GrepKompetansemaal { + implicit val encoder: Encoder[GrepKompetansemaal] = deriveEncoder + implicit val decoder: Decoder[GrepKompetansemaal] = deriveDecoder +} + +case class GrepKompetansemaalSett(kode: String, tittel: Seq[GrepTitle], tilhoerer_laereplan: BelongsToObj) + extends GrepElement + with BelongsToLaerePlan +object GrepKompetansemaalSett { + implicit val encoder: Encoder[GrepKompetansemaalSett] = deriveEncoder + implicit val decoder: Decoder[GrepKompetansemaalSett] = deriveDecoder +} + +case class GrepLaererplan(kode: String, tittel: Seq[GrepTitle]) extends GrepElement +object GrepLaererplan { + implicit val encoder: Encoder[GrepLaererplan] = deriveEncoder + implicit val decoder: Decoder[GrepLaererplan] = deriveDecoder +} -object GrepElement { - implicit val encoder: Encoder[GrepElement] = deriveEncoder - implicit val decoder: Decoder[GrepElement] = deriveDecoder +case class GrepTverrfagligTema(kode: String, tittel: Seq[GrepTitle]) extends GrepElement +object GrepTverrfagligTema { + implicit val encoder: Encoder[GrepTverrfagligTema] = deriveEncoder + implicit val decoder: Decoder[GrepTverrfagligTema] = deriveDecoder } diff --git a/search-api/src/main/scala/no/ndla/searchapi/model/search/SearchableGrepElement.scala b/search-api/src/main/scala/no/ndla/searchapi/model/search/SearchableGrepElement.scala index d62c15de26..7f03e9cdf1 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/model/search/SearchableGrepElement.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/model/search/SearchableGrepElement.scala @@ -15,7 +15,8 @@ import no.ndla.search.model.SearchableLanguageValues case class SearchableGrepElement( code: String, title: SearchableLanguageValues, - defaultTitle: Option[String] + defaultTitle: Option[String], + laereplanCode: Option[String] ) object SearchableGrepElement { diff --git a/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepIndexService.scala b/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepIndexService.scala index 94449c6a2a..8d5a5f8b12 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepIndexService.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepIndexService.scala @@ -35,10 +35,12 @@ trait GrepIndexService { override def getMapping: MappingDefinition = { val fields = List( - keywordField("code").normalizer("lower") + keywordField("defaultTitle"), + keywordField("code").normalizer("lower"), + keywordField("laereplanCode").normalizer("lower") ) - val dynamics = generateLanguageSupportedDynamicTemplates("title", keepRaw = true) + val dynamics = generateLanguageSupportedDynamicTemplates("title", keepRaw = true) properties(fields).dynamicTemplates(dynamics) } diff --git a/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepSearchService.scala b/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepSearchService.scala index 71302f802a..ebd4dc103a 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepSearchService.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/service/search/GrepSearchService.scala @@ -32,7 +32,7 @@ import no.ndla.searchapi.model.search.{SearchType, SearchableGrepElement} import scala.util.{Success, Try} trait GrepSearchService { - this: Props & SearchService & GrepIndexService & BaseIndexService & Elastic4sClient => + this: Props & SearchService & GrepIndexService & BaseIndexService & Elastic4sClient & SearchConverterService => val grepSearchService: GrepSearchService class GrepSearchService extends SearchService { @@ -49,34 +49,52 @@ trait GrepSearchService { case Some(ByCodeDesc) => sortField("code", Desc, missingLast = false) } - protected def buildQuery(input: GrepSearchInputDTO, searchLanguage: String): Query = { - val query = input.query - .map { q => - val langQueryFunc = (fieldName: String, boost: Double) => - buildSimpleStringQueryForField( - q, - fieldName, - boost, - searchLanguage, - fallback = true, - searchDecompounded = true - ) - - val codeQueries = boolQuery().should( - prefixQuery("code", q.underlying).boost(50), - matchQuery("code", q.underlying).boost(10), - termQuery("code", q.underlying).boost(100) - ) - val titleQuery = langQueryFunc("title", 6) + protected def buildCodeQueries(codePrefixes: Set[String], codes: Set[String]): Option[Query] = { + + val prefixQueries = (codePrefixes ++ codes).toList.flatMap { prefix => + List( + prefixQuery("code", prefix).boost(50), + prefixQuery("laereplanCode", prefix).boost(50) + ) + } + + val codeQueries = codes.flatMap { query => + List( + matchQuery("code", query).boost(50), + termQuery("code", query).boost(50), + matchQuery("laereplanCode", query).boost(50), + termQuery("laereplanCode", query).boost(50) + ) + } + + val queries = prefixQueries ++ codeQueries + Option.when(queries.nonEmpty) { boolQuery().should(queries) } + } - val onlyCodeQuery = boolQuery() - .must(codeQueries) - .not(titleQuery) + def extractCodesFromQuery(query: String): Set[String] = { + val regex = """\b([A-Za-z]{2,3}\d{1,4}(?:-\d{1,4})?)\b""".r + regex.findAllIn(query).toSet + } + + def extractCodePrefixesFromQuery(query: String): Set[String] = { + val regex = """\b([A-Za-z]{2,3}(\d{1,4})?(?:-\d{1,4})?)\b""".r + regex.findAllIn(query).toSet + } + + protected def buildQuery(input: GrepSearchInputDTO, searchLanguage: String): Query = { + val query = input.query match { + case Some(q) => + val codes = extractCodesFromQuery(q.underlying) + val codePrefixes = extractCodePrefixesFromQuery(q.underlying) + val codeQueries = buildCodeQueries(codePrefixes, codes) + val titleQuery = languageQuery(q, "title", 6, searchLanguage) boolQuery() - .must(boolQuery().should(titleQuery, onlyCodeQuery)) - } - .getOrElse(boolQuery()) + .withShould(titleQuery) + .withShould(codeQueries) + .minimumShouldMatch(1) + case None => boolQuery() + } query.filter(getFilters(input)) } @@ -109,9 +127,8 @@ trait GrepSearchService { val searchPage = input.page.getOrElse(1) val searchPageSize = input.pageSize.getOrElse(10) val pagination = getStartAtAndNumResults(page = searchPage, pageSize = searchPageSize).? - - val sort = grepSortDefinition(input.sort, searchLanguage) - val filteredQuery = buildQuery(input, searchLanguage) + val sort = grepSortDefinition(input.sort, searchLanguage) + val filteredQuery = buildQuery(input, searchLanguage) val searchToExecute = search(searchIndex) .query(filteredQuery) @@ -133,7 +150,7 @@ trait GrepSearchService { } } - def hitToResult(hit: SearchHit, language: String): Try[GrepResultDTO] = { + private def hitToResult(hit: SearchHit, language: String): Try[GrepResultDTO] = { val jsonString = hit.sourceAsString val searchable = CirceUtil.tryParseAs[SearchableGrepElement](jsonString).? val titleLv = findByLanguageOrBestEffort(searchable.title.languageValues, language) @@ -143,12 +160,13 @@ trait GrepSearchService { Success( GrepResultDTO( code = searchable.code, - title = title + title = title, + laereplanCode = searchable.laereplanCode ) ) } - def getGrepHits(response: RequestSuccess[SearchResponse], language: String): Try[List[GrepResultDTO]] = { + private def getGrepHits(response: RequestSuccess[SearchResponse], language: String): Try[List[GrepResultDTO]] = { response.result.hits.hits.toList.traverse { hit => hitToResult(hit, language) } } } diff --git a/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchConverterService.scala b/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchConverterService.scala index d0432f0bde..f9e650ecf0 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchConverterService.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchConverterService.scala @@ -255,9 +255,8 @@ trait SearchConverterService { } - def asSearchableGrep(grepElement: GrepElement): Try[SearchableGrepElement] = { - val defaultTitle = grepElement.tittel.find(_.spraak == "default") - val titles = grepElement.tittel.flatMap(gt => { + def convertGrepTitleToLanguageValue(grepElement: GrepElement): Seq[LanguageValue[String]] = + grepElement.tittel.flatMap(gt => { ISO639.get6391CodeFor6392Code(gt.spraak) match { case Some(convertedLanguage) => Some(LanguageValue(language = convertedLanguage, value = gt.verdi.trim)) @@ -268,13 +267,21 @@ trait SearchConverterService { } }) - val title = SearchableLanguageValues.fromFields(titles.distinctBy(_.language)) + def asSearchableGrep(grepElement: GrepElement): Try[SearchableGrepElement] = { + val laererplan = grepElement match { + case lp: BelongsToLaerePlan => Some(lp.tilhoerer_laereplan.kode) + case _ => None + } + val defaultTitle = grepElement.tittel.find(_.spraak == "default") + val titles = convertGrepTitleToLanguageValue(grepElement) + val title = SearchableLanguageValues.fromFields(titles) Success( SearchableGrepElement( code = grepElement.kode, title = title, - defaultTitle = defaultTitle.map(_.verdi) + defaultTitle = defaultTitle.map(_.verdi), + laereplanCode = laererplan ) ) } diff --git a/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchService.scala b/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchService.scala index 4776acddd8..a276f858b3 100644 --- a/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchService.scala +++ b/search-api/src/main/scala/no/ndla/searchapi/service/search/SearchService.scala @@ -73,6 +73,9 @@ trait SearchService { } } + def languageQuery(query: NonEmptyString, field: String, boost: Double, language: String): SimpleStringQuery = + buildSimpleStringQueryForField(query, field, boost, language, fallback = true, searchDecompounded = true) + def buildSimpleStringQueryForField( query: NonEmptyString, field: String, diff --git a/search-api/src/test/scala/no/ndla/searchapi/TestData.scala b/search-api/src/test/scala/no/ndla/searchapi/TestData.scala index ee1974653f..204e60fe19 100644 --- a/search-api/src/test/scala/no/ndla/searchapi/TestData.scala +++ b/search-api/src/test/scala/no/ndla/searchapi/TestData.scala @@ -50,7 +50,15 @@ import no.ndla.language.Language.DefaultLanguage import no.ndla.search.model.domain.EmbedValues import no.ndla.search.model.{LanguageValue, SearchableLanguageList, SearchableLanguageValues} import no.ndla.searchapi.model.domain.* -import no.ndla.searchapi.model.grep.{GrepBundle, GrepElement, GrepTitle} +import no.ndla.searchapi.model.grep.{ + BelongsToObj, + GrepBundle, + GrepKjerneelement, + GrepKompetansemaal, + GrepLaererplan, + GrepTitle, + GrepTverrfagligTema +} import no.ndla.searchapi.model.search.* import no.ndla.searchapi.model.search.settings.{MultiDraftSearchSettings, SearchSettings} import no.ndla.searchapi.model.taxonomy.* @@ -1573,21 +1581,24 @@ object TestData { kjerneelementer = List.empty, kompetansemaal = List.empty, kompetansemaalsett = List.empty, - tverrfagligeTemaer = List.empty + tverrfagligeTemaer = List.empty, + laereplaner = List.empty ) val grepBundle: GrepBundle = emptyGrepBundle.copy( kjerneelementer = List( - GrepElement("KE12", Seq(GrepTitle("default", "Utforsking og problemløysing"))), - GrepElement("KE34", Seq(GrepTitle("default", "Abstraksjon og generalisering"))) + GrepKjerneelement("KE12", Seq(GrepTitle("default", "Utforsking og problemløysing")), BelongsToObj("LP1")), + GrepKjerneelement("KE34", Seq(GrepTitle("default", "Abstraksjon og generalisering")), BelongsToObj("LP1")) ), kompetansemaal = List( - GrepElement( + GrepKompetansemaal( "KM123", - Seq(GrepTitle("default", "bruke ulike kilder på en kritisk, hensiktsmessig og etterrettelig måte")) + Seq(GrepTitle("default", "bruke ulike kilder på en kritisk, hensiktsmessig og etterrettelig måte")), + BelongsToObj("LP1") ) ), - tverrfagligeTemaer = List(GrepElement("TT2", Seq(GrepTitle("default", "Demokrati og medborgerskap")))) + tverrfagligeTemaer = List(GrepTverrfagligTema("TT2", Seq(GrepTitle("default", "Demokrati og medborgerskap")))), + laereplaner = List(GrepLaererplan("LP1", Seq(GrepTitle("default", "Læreplan i norsk (NOR01-04)")))) ) val searchSettings: SearchSettings = SearchSettings( diff --git a/search-api/src/test/scala/no/ndla/searchapi/service/search/GrepSearchServiceTest.scala b/search-api/src/test/scala/no/ndla/searchapi/service/search/GrepSearchServiceTest.scala index b434947cf4..e81d40e02c 100644 --- a/search-api/src/test/scala/no/ndla/searchapi/service/search/GrepSearchServiceTest.scala +++ b/search-api/src/test/scala/no/ndla/searchapi/service/search/GrepSearchServiceTest.scala @@ -13,7 +13,15 @@ import no.ndla.scalatestsuite.IntegrationSuite import no.ndla.searchapi.TestEnvironment import no.ndla.searchapi.controller.parameters.GrepSearchInputDTO import no.ndla.searchapi.model.api.grep.GrepSortDTO.{ByCodeAsc, ByCodeDesc} -import no.ndla.searchapi.model.grep.{GrepBundle, GrepElement, GrepTitle} +import no.ndla.searchapi.model.grep.{ + BelongsToObj, + GrepBundle, + GrepKjerneelement, + GrepKompetansemaal, + GrepLaererplan, + GrepTitle, + GrepTverrfagligTema +} class GrepSearchServiceTest extends IntegrationSuite(EnableElasticsearchContainer = true) with TestEnvironment { e4sClient = Elastic4sClientFactory.getClient(elasticSearchHost.getOrElse("")) @@ -39,30 +47,43 @@ class GrepSearchServiceTest extends IntegrationSuite(EnableElasticsearchContaine val grepTestBundle: GrepBundle = GrepBundle( kjerneelementer = List( - GrepElement( + GrepKjerneelement( "KE12", - Seq(GrepTitle("default", "Utforsking og problemløysing"), GrepTitle("nob", "Utforsking og problemløsning")) + Seq(GrepTitle("default", "Utforsking og problemløysing"), GrepTitle("nob", "Utforsking og problemløsning")), + BelongsToObj("LP1") ), - GrepElement( + GrepKjerneelement( "KE34", - Seq(GrepTitle("default", "Abstraksjon og generalisering"), GrepTitle("nob", "Abstraksjon og generalisering")) + Seq(GrepTitle("default", "Abstraksjon og generalisering"), GrepTitle("nob", "Abstraksjon og generalisering")), + BelongsToObj("LP2") ) ), kompetansemaal = List( - GrepElement( + GrepKompetansemaal( "KM123", Seq( GrepTitle("default", "bruke ulike kilder på en kritisk, hensiktsmessig og etterrettelig måte"), GrepTitle("nob", "bruke ulike kilder på en kritisk, hensiktsmessig og etterrettelig måte") - ) + ), + BelongsToObj("LP2") ) ), kompetansemaalsett = List.empty, tverrfagligeTemaer = List( - GrepElement( + GrepTverrfagligTema( "TT2", Seq(GrepTitle("default", "Demokrati og medborgerskap"), GrepTitle("nob", "Demokrati og medborgerskap")) ) + ), + laereplaner = List( + GrepLaererplan( + "LP1", + Seq(GrepTitle("default", "Læreplan i norsk"), GrepTitle("nob", "Læreplan i norsk")) + ), + GrepLaererplan( + "LP2", + Seq(GrepTitle("default", "Læreplan i engelsk"), GrepTitle("nob", "Læreplan i engelsk")) + ) ) ) @@ -140,10 +161,10 @@ class GrepSearchServiceTest extends IntegrationSuite(EnableElasticsearchContaine blockUntil(() => grepIndexService.countDocuments == grepTestBundle.grepContext.size) val result1 = grepSearchService.searchGreps(emptyInput.copy(sort = Some(ByCodeAsc))).get - result1.results.map(_.code) should be(List("KE12", "KE34", "KM123", "TT2")) + result1.results.map(_.code) should be(List("KE12", "KE34", "KM123", "LP1", "LP2", "TT2")) val result2 = grepSearchService.searchGreps(emptyInput.copy(sort = Some(ByCodeDesc))).get - result2.results.map(_.code) should be(List("TT2", "KM123", "KE34", "KE12")) + result2.results.map(_.code) should be(List("TT2", "LP2", "LP1", "KM123", "KE34", "KE12")) } test("That prefix filter is case insensitive") { @@ -153,13 +174,56 @@ class GrepSearchServiceTest extends IntegrationSuite(EnableElasticsearchContaine val result1 = grepSearchService.searchGreps(emptyInput.copy(prefixFilter = Some(List("ke")))).get result1.results.map(_.code) should be(List("KE12", "KE34")) + val result2 = grepSearchService.searchGreps(emptyInput.copy(prefixFilter = Some(List("KE")))).get + result2.results.map(_.code) should be(List("KE12", "KE34")) + } + + test("That query code search is case insensitive") { + grepIndexService.indexDocuments(1.some, Some(grepTestBundle)).get + blockUntil(() => grepIndexService.countDocuments == grepTestBundle.grepContext.size) + + val result1 = grepSearchService.searchGreps(emptyInput.copy(query = NonEmptyString.fromString("KE"))).get + result1.results.map(_.code) should be(List("KE12", "KE34")) + val result2 = grepSearchService.searchGreps(emptyInput.copy(query = NonEmptyString.fromString("ke"))).get result2.results.map(_.code) should be(List("KE12", "KE34")) + } - val result3 = grepSearchService.searchGreps(emptyInput.copy(prefixFilter = Some(List("KE")))).get - result3.results.map(_.code) should be(List("KE12", "KE34")) + test("That searching for a læreplan helps out") { + grepIndexService.indexDocuments(1.some, Some(grepTestBundle)).get + blockUntil(() => grepIndexService.countDocuments == grepTestBundle.grepContext.size) - val result4 = grepSearchService.searchGreps(emptyInput.copy(query = NonEmptyString.fromString("KE"))).get - result4.results.map(_.code) should be(List("KE12", "KE34")) + val result1 = grepSearchService + .searchGreps( + emptyInput.copy( + query = NonEmptyString.fromString("og LP2"), + prefixFilter = Some(List("KE")) + ) + ) + .get + result1.results.map(_.code) should be(List("KE34", "KE12")) + + val result2 = grepSearchService + .searchGreps( + emptyInput.copy( + query = NonEmptyString.fromString("og LP1"), + prefixFilter = Some(List("KE")) + ) + ) + .get + result2.results.map(_.code) should be(List("KE12", "KE34")) + + } + + test("That we are able to extract codes from the query") { + grepSearchService.extractCodesFromQuery("heisann KE12 KE34 KM123 LP1 lille luring LP2 TT2 LMI01-05") should be( + Set("KE12", "KE34", "KM123", "LP1", "LP2", "TT2", "LMI01-05") + ) + } + + test("That we are able to extract codeprefixes from the query") { + grepSearchService.extractCodePrefixesFromQuery("heisann KE LMI APE02- APE05-5") should be( + Set("KE", "LMI", "APE02", "APE05-5") + ) } } diff --git a/search-api/src/test/scala/no/ndla/searchapi/service/search/SearchConverterServiceTest.scala b/search-api/src/test/scala/no/ndla/searchapi/service/search/SearchConverterServiceTest.scala index 2af05318d5..20d0b74c46 100644 --- a/search-api/src/test/scala/no/ndla/searchapi/service/search/SearchConverterServiceTest.scala +++ b/search-api/src/test/scala/no/ndla/searchapi/service/search/SearchConverterServiceTest.scala @@ -13,7 +13,13 @@ import no.ndla.common.model.domain.{ArticleContent, Tag, Title} import no.ndla.search.model.{LanguageValue, SearchableLanguageList, SearchableLanguageValues} import no.ndla.searchapi.caching.Memoize import no.ndla.searchapi.model.domain.IndexingBundle -import no.ndla.searchapi.model.grep.{GrepElement, GrepTitle} +import no.ndla.searchapi.model.grep.{ + BelongsToObj, + GrepKjerneelement, + GrepKompetansemaal, + GrepTitle, + GrepTverrfagligTema +} import no.ndla.searchapi.model.search.{SearchTrait, SearchableArticle, SearchableGrepContext} import no.ndla.searchapi.model.taxonomy.* import no.ndla.searchapi.{TestData, TestEnvironment, UnitSuite} @@ -490,11 +496,11 @@ class SearchConverterServiceTest extends UnitSuite with TestEnvironment { val draft = TestData.emptyDomainDraft.copy(id = Some(99), grepCodes = Seq("KE12", "KM123", "TT2")) val grepBundle = TestData.emptyGrepBundle.copy( kjerneelementer = List( - GrepElement("KE12", Seq(GrepTitle("default", "tittel12"))), - GrepElement("KE34", Seq(GrepTitle("default", "tittel34"))) + GrepKjerneelement("KE12", Seq(GrepTitle("default", "tittel12")), BelongsToObj("LP123")), + GrepKjerneelement("KE34", Seq(GrepTitle("default", "tittel34")), BelongsToObj("LP123")) ), - kompetansemaal = List(GrepElement("KM123", Seq(GrepTitle("default", "tittel123")))), - tverrfagligeTemaer = List(GrepElement("TT2", Seq(GrepTitle("default", "tittel2")))) + kompetansemaal = List(GrepKompetansemaal("KM123", Seq(GrepTitle("default", "tittel123")), BelongsToObj("LP123"))), + tverrfagligeTemaer = List(GrepTverrfagligTema("TT2", Seq(GrepTitle("default", "tittel2")))) ) val grepContexts = List( SearchableGrepContext("KE12", Some("tittel12")), @@ -510,11 +516,11 @@ class SearchConverterServiceTest extends UnitSuite with TestEnvironment { val draft = TestData.emptyDomainDraft.copy(id = Some(99), grepCodes = Seq.empty) val grepBundle = TestData.emptyGrepBundle.copy( kjerneelementer = List( - GrepElement("KE12", Seq(GrepTitle("default", "tittel12"))), - GrepElement("KE34", Seq(GrepTitle("default", "tittel34"))) + GrepKjerneelement("KE12", Seq(GrepTitle("default", "tittel12")), BelongsToObj("LP123")), + GrepKjerneelement("KE34", Seq(GrepTitle("default", "tittel34")), BelongsToObj("LP123")) ), - kompetansemaal = List(GrepElement("KM123", Seq(GrepTitle("default", "tittel123")))), - tverrfagligeTemaer = List(GrepElement("TT2", Seq(GrepTitle("default", "tittel2")))) + kompetansemaal = List(GrepKompetansemaal("KM123", Seq(GrepTitle("default", "tittel123")), BelongsToObj("LP123"))), + tverrfagligeTemaer = List(GrepTverrfagligTema("TT2", Seq(GrepTitle("default", "tittel2")))) ) val grepContexts = List.empty