Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add highlights and source to inner hits #225

Merged
merged 7 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"))
dbulaja98 marked this conversation as resolved.
Show resolved Hide resolved
.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