mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-05 22:55:58 +00:00
Allow updating single fields in solr
This commit is contained in:
parent
1f4ff0d4c4
commit
383614f908
@ -1,6 +1,7 @@
|
|||||||
package docspell.ftssolr
|
package docspell.ftssolr
|
||||||
|
|
||||||
import io.circe._
|
import io.circe._
|
||||||
|
import docspell.common._
|
||||||
|
|
||||||
final class Field(val name: String) extends AnyVal {
|
final class Field(val name: String) extends AnyVal {
|
||||||
|
|
||||||
@ -12,19 +13,25 @@ object Field {
|
|||||||
def apply(name: String): Field =
|
def apply(name: String): Field =
|
||||||
new Field(name)
|
new Field(name)
|
||||||
|
|
||||||
|
val id = Field("id")
|
||||||
val id = Field("id")
|
val itemId = Field("itemId")
|
||||||
val itemId = Field("itemId")
|
val collectiveId = Field("collectiveId")
|
||||||
val collectiveId = Field("collectiveId")
|
val attachmentId = Field("attachmentId")
|
||||||
val attachmentId = Field("attachmentId")
|
val discriminator = Field("discriminator")
|
||||||
val discriminator = Field("discriminator")
|
|
||||||
val attachmentName = Field("attachmentName")
|
val attachmentName = Field("attachmentName")
|
||||||
val content = Field("content")
|
val content = Field("content")
|
||||||
val content_de = Field("content_de")
|
val content_de = Field("content_de")
|
||||||
val content_en = Field("content_en")
|
val content_en = Field("content_en")
|
||||||
val itemName = Field("itemName")
|
val itemName = Field("itemName")
|
||||||
val itemNotes = Field("itemNotes")
|
val itemNotes = Field("itemNotes")
|
||||||
|
|
||||||
|
def contentField(lang: Language): Field =
|
||||||
|
lang match {
|
||||||
|
case Language.German =>
|
||||||
|
Field.content_de
|
||||||
|
case Language.English =>
|
||||||
|
Field.content_en
|
||||||
|
}
|
||||||
|
|
||||||
implicit val jsonEncoder: Encoder[Field] =
|
implicit val jsonEncoder: Encoder[Field] =
|
||||||
Encoder.encodeString.contramap(_.name)
|
Encoder.encodeString.contramap(_.name)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package docspell.ftssolr
|
package docspell.ftssolr
|
||||||
|
|
||||||
import io.circe._
|
import io.circe._
|
||||||
|
import io.circe.syntax._
|
||||||
import docspell.common._
|
import docspell.common._
|
||||||
import docspell.ftsclient._
|
import docspell.ftsclient._
|
||||||
|
|
||||||
@ -12,15 +13,7 @@ trait JsonCodec {
|
|||||||
new Encoder[TextData.Attachment] {
|
new Encoder[TextData.Attachment] {
|
||||||
final def apply(td: TextData.Attachment): Json = {
|
final def apply(td: TextData.Attachment): Json = {
|
||||||
val cnt =
|
val cnt =
|
||||||
(
|
(Field.contentField(td.lang).name, Json.fromString(td.text.getOrElse("")))
|
||||||
td.lang match {
|
|
||||||
case Language.German =>
|
|
||||||
Field.content_de.name
|
|
||||||
case Language.English =>
|
|
||||||
Field.content_en.name
|
|
||||||
},
|
|
||||||
Json.fromString(td.text.getOrElse(""))
|
|
||||||
)
|
|
||||||
|
|
||||||
Json.fromFields(
|
Json.fromFields(
|
||||||
cnt :: List(
|
cnt :: List(
|
||||||
@ -100,6 +93,41 @@ trait JsonCodec {
|
|||||||
new KeyDecoder[Ident] {
|
new KeyDecoder[Ident] {
|
||||||
override def apply(ident: String): Option[Ident] = Ident(ident).toOption
|
override def apply(ident: String): Option[Ident] = Ident(ident).toOption
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def setAttachmentEncoder(implicit
|
||||||
|
enc: Encoder[Ident]
|
||||||
|
): Encoder[TextData.Attachment] =
|
||||||
|
new Encoder[TextData.Attachment] {
|
||||||
|
final def apply(td: TextData.Attachment): Json = {
|
||||||
|
val setter = List(
|
||||||
|
td.name.map(n => (Field.attachmentName.name, Map("set" -> n.asJson).asJson)),
|
||||||
|
td.text.map(txt =>
|
||||||
|
(Field.contentField(td.lang).name, Map("set" -> txt.asJson).asJson)
|
||||||
|
)
|
||||||
|
).flatten
|
||||||
|
Json.fromFields(
|
||||||
|
(Field.id.name, enc(td.id)) :: setter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def setItemEncoder(implicit enc: Encoder[Ident]): Encoder[TextData.Item] =
|
||||||
|
new Encoder[TextData.Item] {
|
||||||
|
final def apply(td: TextData.Item): Json = {
|
||||||
|
val setter = List(
|
||||||
|
td.name.map(n => (Field.itemName.name, Map("set" -> n.asJson).asJson)),
|
||||||
|
td.notes.map(n => (Field.itemNotes.name, Map("set" -> n.asJson).asJson))
|
||||||
|
).flatten
|
||||||
|
|
||||||
|
Json.fromFields(
|
||||||
|
(Field.id.name, enc(td.id)) :: setter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit def textDataEncoder: Encoder[SetFields] =
|
||||||
|
Encoder(_.td.fold(setAttachmentEncoder.apply, setItemEncoder.apply))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object JsonCodec extends JsonCodec
|
object JsonCodec extends JsonCodec
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package docspell.ftssolr
|
||||||
|
|
||||||
|
import docspell.ftsclient._
|
||||||
|
|
||||||
|
final case class SetFields(td: TextData)
|
@ -24,7 +24,7 @@ final class SolrFtsClient[F[_]: Effect](
|
|||||||
(for {
|
(for {
|
||||||
_ <- Stream.eval(logger.debug("Inserting data into index"))
|
_ <- Stream.eval(logger.debug("Inserting data into index"))
|
||||||
chunks <- data.chunks
|
chunks <- data.chunks
|
||||||
res <- Stream.eval(solrUpdate.many(chunks.toList).attempt)
|
res <- Stream.eval(solrUpdate.add(chunks.toList).attempt)
|
||||||
_ <- res match {
|
_ <- res match {
|
||||||
case Right(()) => Stream.emit(())
|
case Right(()) => Stream.emit(())
|
||||||
case Left(ex) =>
|
case Left(ex) =>
|
||||||
|
@ -82,7 +82,9 @@ object SolrSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schema Commands
|
// Schema Commands: The structure is for conveniently creating the
|
||||||
|
// solr json. All fields must be stored, because of highlighting and
|
||||||
|
// single-updates only work when all fields are stored.
|
||||||
|
|
||||||
case class AddField(
|
case class AddField(
|
||||||
name: Field,
|
name: Field,
|
||||||
|
@ -14,9 +14,9 @@ import JsonCodec._
|
|||||||
|
|
||||||
trait SolrUpdate[F[_]] {
|
trait SolrUpdate[F[_]] {
|
||||||
|
|
||||||
def single(td: TextData): F[Unit]
|
def add(tds: List[TextData]): F[Unit]
|
||||||
|
|
||||||
def many(tds: List[TextData]): F[Unit]
|
def update(tds: List[TextData]): F[Unit]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,15 +33,24 @@ object SolrUpdate {
|
|||||||
.withQueryParam("overwrite", "true")
|
.withQueryParam("overwrite", "true")
|
||||||
.withQueryParam("wt", "json")
|
.withQueryParam("wt", "json")
|
||||||
|
|
||||||
def single(td: TextData): F[Unit] = {
|
|
||||||
val req = Method.POST(td.asJson, url)
|
|
||||||
client.expect[String](req).map(r => logger.debug(s"Req: $req Response: $r"))
|
|
||||||
}
|
|
||||||
|
|
||||||
def many(tds: List[TextData]): F[Unit] = {
|
def add(tds: List[TextData]): F[Unit] = {
|
||||||
val req = Method.POST(tds.asJson, url)
|
val req = Method.POST(tds.asJson, url)
|
||||||
client.expect[String](req).map(r => logger.debug(s"Req: $req Response: $r"))
|
client.expect[String](req).map(r => logger.debug(s"Req: $req Response: $r"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def update(tds: List[TextData]): F[Unit] = {
|
||||||
|
val req = Method.POST(tds.filter(minOneChange).map(SetFields).asJson, url)
|
||||||
|
client.expect[String](req).map(r => logger.debug(s"Req: $req Response: $r"))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val minOneChange: TextData => Boolean =
|
||||||
|
_ match {
|
||||||
|
case td: TextData.Attachment =>
|
||||||
|
td.name.isDefined || td.text.isDefined
|
||||||
|
case td: TextData.Item =>
|
||||||
|
td.name.isDefined || td.notes.isDefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user