Refactor findItemsWithTags to more general useful

This commit is contained in:
Eike Kettner 2020-06-23 21:27:01 +02:00
parent 647911563e
commit d9f0f05613
4 changed files with 24 additions and 8 deletions

View File

@ -110,11 +110,15 @@ object OItemSearch {
.compile .compile
.toVector .toVector
def findItemsWithTags(q: Query, batch: Batch): F[Vector[ListItemWithTags]] = def findItemsWithTags(q: Query, batch: Batch): F[Vector[ListItemWithTags]] = {
val search = QItem.findItems(q, batch)
store store
.transact(QItem.findItemsWithTags(q, batch).take(batch.limit.toLong)) .transact(
QItem.findItemsWithTags(q.collective, search).take(batch.limit.toLong)
)
.compile .compile
.toVector .toVector
}
def findAttachment(id: Ident, collective: Ident): F[Option[AttachmentData[F]]] = def findAttachment(id: Ident, collective: Ident): F[Option[AttachmentData[F]]] =
store store

View File

@ -24,6 +24,7 @@ trait FtsClient[F[_]] {
/** Run a full-text search. */ /** Run a full-text search. */
def search(q: FtsQuery): F[FtsResult] def search(q: FtsQuery): F[FtsResult]
/** Continually run a full-text search and concatenate the results. */
def searchAll(q: FtsQuery): Stream[F, FtsResult] = def searchAll(q: FtsQuery): Stream[F, FtsResult] =
Stream.eval(search(q)).flatMap { result => Stream.eval(search(q)).flatMap { result =>
if (result.results.size < q.limit) Stream.emit(result) if (result.results.size < q.limit) Stream.emit(result)

View File

@ -8,7 +8,8 @@ import docspell.common._
* interpret it according to the system in use. * interpret it according to the system in use.
* *
* Searches must only look for given collective and in the given list * Searches must only look for given collective and in the given list
* of item ids. * of item ids, if it is non-empty. If the item set is empty, then
* don't restrict the result in this way.
*/ */
final case class FtsQuery( final case class FtsQuery(
q: String, q: String,

View File

@ -214,7 +214,7 @@ object QItem {
Batch(0, c) Batch(0, c)
} }
def findItems(q: Query, batch: Batch): Stream[ConnectionIO, ListItem] = { private def findItemsBase(q: Query): Fragment = {
val IC = RItem.Columns val IC = RItem.Columns
val AC = RAttachment.Columns val AC = RAttachment.Columns
val PC = RPerson.Columns val PC = RPerson.Columns
@ -271,6 +271,16 @@ object QItem {
fr"LEFT JOIN orgs o0 ON" ++ IC.corrOrg.prefix("i").is(OC.oid.prefix("o0")) ++ fr"LEFT JOIN orgs o0 ON" ++ IC.corrOrg.prefix("i").is(OC.oid.prefix("o0")) ++
fr"LEFT JOIN persons p1 ON" ++ IC.concPerson.prefix("i").is(PC.pid.prefix("p1")) ++ fr"LEFT JOIN persons p1 ON" ++ IC.concPerson.prefix("i").is(PC.pid.prefix("p1")) ++
fr"LEFT JOIN equips e1 ON" ++ IC.concEquipment.prefix("i").is(EC.eid.prefix("e1")) fr"LEFT JOIN equips e1 ON" ++ IC.concEquipment.prefix("i").is(EC.eid.prefix("e1"))
query
}
def findItems(q: Query, batch: Batch): Stream[ConnectionIO, ListItem] = {
val IC = RItem.Columns
val PC = RPerson.Columns
val OC = ROrganization.Columns
val EC = REquipment.Columns
val query = findItemsBase(q)
// inclusive tags are AND-ed // inclusive tags are AND-ed
val tagSelectsIncl = q.tagsInclude val tagSelectsIncl = q.tagsInclude
@ -370,8 +380,8 @@ object QItem {
* this is implemented by running an additional query per item. * this is implemented by running an additional query per item.
*/ */
def findItemsWithTags( def findItemsWithTags(
q: Query, collective: Ident,
batch: Batch search: Stream[ConnectionIO, ListItem]
): Stream[ConnectionIO, ListItemWithTags] = { ): Stream[ConnectionIO, ListItemWithTags] = {
def findTag( def findTag(
cache: Ref[ConnectionIO, Map[Ident, RTag]], cache: Ref[ConnectionIO, Map[Ident, RTag]],
@ -394,10 +404,10 @@ object QItem {
for { for {
resolvedTags <- Stream.eval(Ref.of[ConnectionIO, Map[Ident, RTag]](Map.empty)) resolvedTags <- Stream.eval(Ref.of[ConnectionIO, Map[Ident, RTag]](Map.empty))
item <- findItems(q, batch) item <- search
tagItems <- Stream.eval(RTagItem.findByItem(item.id)) tagItems <- Stream.eval(RTagItem.findByItem(item.id))
tags <- Stream.eval(tagItems.traverse(ti => findTag(resolvedTags, ti))) tags <- Stream.eval(tagItems.traverse(ti => findTag(resolvedTags, ti)))
ftags = tags.flatten.filter(t => t.collective == q.collective) ftags = tags.flatten.filter(t => t.collective == collective)
} yield ListItemWithTags(item, ftags.toList.sortBy(_.name)) } yield ListItemWithTags(item, ftags.toList.sortBy(_.name))
} }