mirror of
				https://github.com/TheAnachronism/docspell.git
				synced 2025-10-30 21:40:12 +00:00 
			
		
		
		
	Add summary for fulltext searches
This commit is contained in:
		| @@ -445,7 +445,8 @@ val joex = project | ||||
|     buildInfoPackage := "docspell.joex", | ||||
|     reStart / javaOptions ++= Seq( | ||||
|       s"-Dconfig.file=${(LocalRootProject / baseDirectory).value / "local" / "dev.conf"}" | ||||
|     ) | ||||
|     ), | ||||
|     Revolver.enableDebugging(port = 5051, suspend = false) | ||||
|   ) | ||||
|   .dependsOn(store, backend, extract, convert, analysis, joexapi, restapi, ftssolr) | ||||
|  | ||||
| @@ -492,7 +493,8 @@ val restserver = project | ||||
|     ), | ||||
|     reStart / javaOptions ++= Seq( | ||||
|       s"-Dconfig.file=${(LocalRootProject / baseDirectory).value / "local" / "dev.conf"}" | ||||
|     ) | ||||
|     ), | ||||
|     Revolver.enableDebugging(port = 5050, suspend = false) | ||||
|   ) | ||||
|   .dependsOn(restapi, joexapi, backend, webapp, ftssolr) | ||||
|  | ||||
|   | ||||
| @@ -7,12 +7,15 @@ import fs2.Stream | ||||
| import docspell.backend.JobFactory | ||||
| import docspell.backend.ops.OItemSearch._ | ||||
| import docspell.common._ | ||||
| import docspell.common.syntax.all._ | ||||
| import docspell.ftsclient._ | ||||
| import docspell.store.queries.{QFolder, QItem, SelectedItem} | ||||
| import docspell.store.queue.JobQueue | ||||
| import docspell.store.records.RJob | ||||
| import docspell.store.{Store, qb} | ||||
|  | ||||
| import org.log4s.getLogger | ||||
|  | ||||
| trait OFulltext[F[_]] { | ||||
|  | ||||
|   def findItems(maxNoteLen: Int)( | ||||
| @@ -34,6 +37,9 @@ trait OFulltext[F[_]] { | ||||
|       batch: qb.Batch | ||||
|   ): F[Vector[OFulltext.FtsItemWithTags]] | ||||
|  | ||||
|   def findIndexOnlySummary(account: AccountId, fts: OFulltext.FtsInput): F[SearchSummary] | ||||
|   def findItemsSummary(q: Query, fts: OFulltext.FtsInput): F[SearchSummary] | ||||
|  | ||||
|   /** Clears the full-text index completely and launches a task that | ||||
|     * indexes all data. | ||||
|     */ | ||||
| @@ -46,6 +52,7 @@ trait OFulltext[F[_]] { | ||||
| } | ||||
|  | ||||
| object OFulltext { | ||||
|   private[this] val logger = getLogger | ||||
|  | ||||
|   case class FtsInput( | ||||
|       query: String, | ||||
| @@ -77,12 +84,14 @@ object OFulltext { | ||||
|     Resource.pure[F, OFulltext[F]](new OFulltext[F] { | ||||
|       def reindexAll: F[Unit] = | ||||
|         for { | ||||
|           _   <- logger.finfo(s"Re-index all.") | ||||
|           job <- JobFactory.reIndexAll[F] | ||||
|           _   <- queue.insertIfNew(job) *> joex.notifyAllNodes | ||||
|         } yield () | ||||
|  | ||||
|       def reindexCollective(account: AccountId): F[Unit] = | ||||
|         for { | ||||
|           _ <- logger.fdebug(s"Re-index collective: $account") | ||||
|           exist <- store.transact( | ||||
|             RJob.findNonFinalByTracker(DocspellSystem.migrationTaskTracker) | ||||
|           ) | ||||
| @@ -107,6 +116,7 @@ object OFulltext { | ||||
|           FtsQuery.HighlightSetting(ftsQ.highlightPre, ftsQ.highlightPost) | ||||
|         ) | ||||
|         for { | ||||
|           _       <- logger.ftrace(s"Find index only: ${ftsQ.query}/${batch}") | ||||
|           folders <- store.transact(QFolder.getMemberFolders(account)) | ||||
|           ftsR    <- fts.search(fq.withFolders(folders)) | ||||
|           ftsItems = ftsR.results.groupBy(_.itemId) | ||||
| @@ -133,6 +143,32 @@ object OFulltext { | ||||
|         } yield res | ||||
|       } | ||||
|  | ||||
|       def findIndexOnlySummary( | ||||
|           account: AccountId, | ||||
|           ftsQ: OFulltext.FtsInput | ||||
|       ): F[SearchSummary] = { | ||||
|         val fq = FtsQuery( | ||||
|           ftsQ.query, | ||||
|           account.collective, | ||||
|           Set.empty, | ||||
|           Set.empty, | ||||
|           500, | ||||
|           0, | ||||
|           FtsQuery.HighlightSetting.default | ||||
|         ) | ||||
|  | ||||
|         for { | ||||
|           folder <- store.transact(QFolder.getMemberFolders(account)) | ||||
|           itemIds <- fts | ||||
|             .searchAll(fq.withFolders(folder)) | ||||
|             .flatMap(r => Stream.emits(r.results.map(_.itemId))) | ||||
|             .compile | ||||
|             .to(Set) | ||||
|           q = Query.empty(account).copy(itemIds = itemIds.some) | ||||
|           res <- store.transact(QItem.searchStats(q)) | ||||
|         } yield res | ||||
|       } | ||||
|  | ||||
|       def findItems( | ||||
|           maxNoteLen: Int | ||||
|       )(q: Query, ftsQ: FtsInput, batch: qb.Batch): F[Vector[FtsItem]] = | ||||
| @@ -167,6 +203,27 @@ object OFulltext { | ||||
|           .compile | ||||
|           .toVector | ||||
|  | ||||
|       def findItemsSummary(q: Query, ftsQ: OFulltext.FtsInput): F[SearchSummary] = | ||||
|         for { | ||||
|           search <- itemSearch.findItems(0)(q, Batch.all) | ||||
|           fq = FtsQuery( | ||||
|             ftsQ.query, | ||||
|             q.account.collective, | ||||
|             search.map(_.id).toSet, | ||||
|             Set.empty, | ||||
|             500, | ||||
|             0, | ||||
|             FtsQuery.HighlightSetting.default | ||||
|           ) | ||||
|           items <- fts | ||||
|             .searchAll(fq) | ||||
|             .flatMap(r => Stream.emits(r.results.map(_.itemId))) | ||||
|             .compile | ||||
|             .to(Set) | ||||
|           qnext = q.copy(itemIds = items.some) | ||||
|           res <- store.transact(QItem.searchStats(qnext)) | ||||
|         } yield res | ||||
|  | ||||
|       // Helper | ||||
|  | ||||
|       private def findItemsFts[A: ItemId, B]( | ||||
|   | ||||
| @@ -147,7 +147,18 @@ object ItemRoutes { | ||||
|         for { | ||||
|           mask <- req.as[ItemSearch] | ||||
|           query = Conversions.mkQuery(mask, user.account) | ||||
|           stats <- backend.itemSearch.findItemsSummary(query) | ||||
|           stats <- mask match { | ||||
|             case SearchFulltextOnly(ftq) if cfg.fullTextSearch.enabled => | ||||
|               logger.finfo(s"Make index only summary: $ftq") *> | ||||
|                 backend.fulltext.findIndexOnlySummary( | ||||
|                   user.account, | ||||
|                   OFulltext.FtsInput(ftq.query) | ||||
|                 ) | ||||
|             case SearchWithFulltext(fq) if cfg.fullTextSearch.enabled => | ||||
|               backend.fulltext.findItemsSummary(query, OFulltext.FtsInput(fq)) | ||||
|             case _ => | ||||
|               backend.itemSearch.findItemsSummary(query) | ||||
|           } | ||||
|           resp <- Ok(Conversions.mkSearchStats(stats)) | ||||
|         } yield resp | ||||
|  | ||||
|   | ||||
| @@ -201,11 +201,19 @@ viewStats _ model = | ||||
|         fields = | ||||
|             List.filter isNumField stats.fieldStats | ||||
|     in | ||||
|     if List.isEmpty fields then | ||||
|         [] | ||||
|  | ||||
|     else | ||||
|     [ div [ class "ui container" ] | ||||
|         [ div [ class "ui middle aligned grid" ] | ||||
|             [ div [ class "three wide center aligned column" ] | ||||
|                 [ div [ class "ui small statistic" ] | ||||
|                     [ div [ class "value" ] | ||||
|                         [ String.fromInt stats.count |> text | ||||
|                         ] | ||||
|                     , div [ class "label" ] | ||||
|                         [ text "Results" | ||||
|                         ] | ||||
|                     ] | ||||
|                 ] | ||||
|             , div [ class "thirteen wide column" ] | ||||
|                 [ table [ class "ui very basic tiny six column table" ] | ||||
|                     [ thead [] | ||||
|                         [ tr [ class "center aligned" ] | ||||
| @@ -222,6 +230,8 @@ viewStats _ model = | ||||
|                     ] | ||||
|                 ] | ||||
|             ] | ||||
|         ] | ||||
|     ] | ||||
|  | ||||
|  | ||||
| viewLeftMenu : Flags -> UiSettings -> Model -> List (Html Msg) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user