Skip to content

Commit

Permalink
Add highlights and source to inner hits (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbulaja98 authored May 22, 2023
1 parent 87507ad commit f81f995
Show file tree
Hide file tree
Showing 3 changed files with 418 additions and 9 deletions.
124 changes: 120 additions & 4 deletions modules/library/src/main/scala/zio/elasticsearch/query/InnerHits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,145 @@
package zio.elasticsearch.query

import zio.Chunk
import zio.elasticsearch.ElasticPrimitive.ElasticPrimitiveOps
import zio.elasticsearch.Field
import zio.elasticsearch.highlights.Highlights
import zio.json.ast.Json
import zio.json.ast.Json.{Num, Obj, Str}
import zio.json.ast.Json.{Arr, Num, Obj, Str}

final case class InnerHits private[elasticsearch] (
private val excluded: Chunk[String],
private val included: Chunk[String],
private val from: Option[Int],
private val highlights: Option[Highlights],
private val name: Option[String],
private val size: Option[Int]
) { self =>

/**
* Specifies one or more type-safe fields to be excluded in the response of a [[zio.elasticsearch.query.InnerHits]].
*
* @param field
* a type-safe field to be excluded
* @param fields
* type-safe fields to be excluded
* @tparam S
* document which fields are excluded
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with specified fields to be excluded.
*/
def excludes[S](field: Field[S, _], fields: Field[S, _]*): InnerHits =
self.copy(excluded = excluded ++ (field.toString +: fields.map(_.toString)))

/**
* Specifies one or more fields to be excluded in the response of a [[zio.elasticsearch.query.InnerHits]].
*
* @param field
* a field to be excluded
* @param fields
* fields to be excluded
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with specified fields to be excluded.
*/
def excludes(field: String, fields: String*): InnerHits =
self.copy(excluded = excluded ++ (field +: fields))

/**
* Specifies the starting offset of the [[zio.elasticsearch.query.InnerHits]] to be returned.
*
* @param value
* the starting offset value
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with the specified starting offset.
*/
def from(value: Int): InnerHits =
self.copy(from = Some(value))

/**
* Specifies the highlighting configuration for the [[zio.elasticsearch.query.InnerHits]].
*
* @param value
* the [[zio.elasticsearch.highlights.Highlights]] configuration
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with the specified highlighting configuration.
*/
def highlights(value: Highlights): InnerHits =
self.copy(highlights = Some(value))

/**
* Specifies one or more type-safe fields to be included in the response of a [[zio.elasticsearch.query.InnerHits]].
*
* @param field
* a type-safe field to be included
* @param fields
* type-safe fields to be included
* @tparam S
* document which fields are included
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with specified fields to be included.
*/
def includes[S](field: Field[S, _], fields: Field[S, _]*): InnerHits =
self.copy(included = included ++ (field.toString +: fields.map(_.toString)))

/**
* Specifies one or more fields to be included in the response of a [[zio.elasticsearch.query.InnerHits]].
*
* @param field
* a field to be included
* @param fields
* fields to be included
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with specified fields to be included.
*/
def includes(field: String, fields: String*): InnerHits =
self.copy(included = included ++ (field +: fields))

/**
* Specifies the name of the [[zio.elasticsearch.query.InnerHits]].
*
* @param value
* the name of the [[zio.elasticsearch.query.InnerHits]]
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with the specified name.
*/
def name(value: String): InnerHits =
self.copy(name = Some(value))

/**
* Specifies the maximum number of [[zio.elasticsearch.query.InnerHits]] to be returned.
*
* @param value
* the maximum number of [[zio.elasticsearch.query.InnerHits]]
* @return
* an instance of a [[zio.elasticsearch.query.InnerHits]] with the specified size.
*/
def size(value: Int): InnerHits =
self.copy(size = Some(value))

def toStringJsonPair: (String, Json) =
private[elasticsearch] def toStringJsonPair: (String, Json) = {
val sourceJson: Option[Json] =
(included, excluded) match {
case (Chunk(), Chunk()) =>
None
case (included, excluded) =>
val includes = if (included.isEmpty) Obj() else Obj("includes" -> Arr(included.map(_.toJson)))
val excludes = if (excluded.isEmpty) Obj() else Obj("excludes" -> Arr(excluded.map(_.toJson)))
Some(includes merge excludes)
}

"inner_hits" -> Obj(
Chunk(from.map("from" -> Num(_)), size.map("size" -> Num(_)), name.map("name" -> Str(_))).flatten
Chunk(
from.map("from" -> Num(_)),
size.map("size" -> Num(_)),
name.map("name" -> Str(_)),
highlights.map("highlight" -> _.toJson),
sourceJson.map("_source" -> _)
).flatten
)
}
}

object InnerHits {
def apply(): InnerHits = InnerHits(from = None, name = None, size = None)
def apply(): InnerHits =
InnerHits(excluded = Chunk(), included = Chunk(), from = None, highlights = None, name = None, size = None)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package zio.elasticsearch

import zio.Chunk
import zio.elasticsearch.ElasticHighlight.highlight
import zio.elasticsearch.ElasticQuery._
import zio.elasticsearch.domain._
import zio.elasticsearch.query.DistanceType.Plane
Expand Down Expand Up @@ -761,7 +762,16 @@ object ElasticQuerySpec extends ZIOSpecDefault {
query = MatchAll(boost = None),
scoreMode = None,
ignoreUnmapped = None,
innerHitsField = Some(InnerHits(from = Some(0), name = Some("innerHitName"), size = Some(3)))
innerHitsField = Some(
InnerHits(
excluded = Chunk(),
included = Chunk(),
from = Some(0),
highlights = None,
name = Some("innerHitName"),
size = Some(3)
)
)
)
)
) &&
Expand All @@ -772,7 +782,16 @@ object ElasticQuerySpec extends ZIOSpecDefault {
query = MatchAll(boost = None),
scoreMode = None,
ignoreUnmapped = None,
innerHitsField = Some(InnerHits(None, None, None))
innerHitsField = Some(
InnerHits(
excluded = Chunk(),
included = Chunk(),
from = None,
highlights = None,
name = None,
size = None
)
)
)
)
) &&
Expand All @@ -794,7 +813,16 @@ object ElasticQuerySpec extends ZIOSpecDefault {
query = MatchAll(boost = None),
scoreMode = Some(ScoreMode.Max),
ignoreUnmapped = Some(false),
innerHitsField = Some(InnerHits(None, Some("innerHitName"), None))
innerHitsField = Some(
InnerHits(
excluded = Chunk(),
included = Chunk(),
from = None,
highlights = None,
name = Some("innerHitName"),
size = None
)
)
)
)
)
Expand Down Expand Up @@ -2027,7 +2055,15 @@ object ElasticQuerySpec extends ZIOSpecDefault {
val queryWithNested = nested(TestDocument.subDocumentList, nested("items", term("testField", "test")))
val queryWithIgnoreUnmapped = nested(TestDocument.subDocumentList, matchAll).ignoreUnmappedTrue
val queryWithInnerHits =
nested(TestDocument.subDocumentList, matchAll).innerHits(InnerHits().from(0).size(3).name("innerHitName"))
nested(TestDocument.subDocumentList, matchAll).innerHits(
InnerHits()
.from(0)
.size(3)
.name("innerHitName")
.highlights(highlight("stringField"))
.excludes("longField")
.includes("intField")
)
val queryWithInnerHitsEmpty = nested(TestDocument.subDocumentList, matchAll).innerHits
val queryWithScoreMode = nested(TestDocument.subDocumentList, matchAll).scoreMode(ScoreMode.Avg)
val queryWithAllParams = nested(TestDocument.subDocumentList, matchAll).ignoreUnmappedFalse
Expand Down Expand Up @@ -2091,7 +2127,20 @@ object ElasticQuerySpec extends ZIOSpecDefault {
| "inner_hits": {
| "from": 0,
| "size": 3,
| "name": "innerHitName"
| "name": "innerHitName",
| "highlight" : {
| "fields" : {
| "stringField" : {}
| }
| },
| "_source" : {
| "includes" : [
| "intField"
| ],
| "excludes" : [
| "longField"
| ]
| }
| }
| }
|}
Expand Down
Loading

0 comments on commit f81f995

Please sign in to comment.