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

(dsl): Support highlights #141

Merged
merged 13 commits into from
Apr 4, 2023
Merged

(dsl): Support highlights #141

merged 13 commits into from
Apr 4, 2023

Conversation

markaya
Copy link
Contributor

@markaya markaya commented Mar 31, 2023

No description provided.

def highlight[S](field: Field[S, _], fieldConfig: Map[String, Json]): Highlights =
Highlights(Chunk(HighlightField(field.toString, fieldConfig)))

def highlight(field: String, fieldConfig: Map[String, Json] = Map.empty): Highlights =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use config instead of fieldConfig?

@@ -69,10 +70,17 @@ object ElasticRequest {
GetById(index = index, id = id, refresh = None, routing = None)

def search(index: IndexName, query: ElasticQuery[_]): SearchRequest =
Search(index = index, query = query, sortBy = Set.empty, routing = None)
Search(index = index, query = query, sortBy = Set.empty, routing = None, highlights = None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put this before routing. Let's use sorted params.

aggregation = aggregation,
sortBy = Set.empty,
routing = None,
highlights = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@@ -311,16 +319,29 @@ object ElasticRequest {
with HasRouting[SearchRequest]
with WithSort[SearchRequest] {
def aggregate(aggregation: ElasticAggregation): SearchAndAggregateRequest
def highlights(value: Highlights): Search
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about highlighted(highlights: Highlights). What do you think? Also, add a new line before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe to use highlight to have meaning as a verb. (I want this search and highlight this)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a new line before?

import zio.json.ast.Json
import zio.json.ast.Json.Obj

case class Highlights(fields: Chunk[HighlightField], globalConfig: HighlightConfig = Map.empty) { self =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add final here.

import zio.json.ast.Json
import zio.json.ast.Json.Obj

case class Highlights(fields: Chunk[HighlightField], globalConfig: HighlightConfig = Map.empty) { self =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use config here instead of globalConfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have config parameter in method, maybe it would not be clear.

def withGlobalConfig(configFieldName: String, config: Json): Highlights =
self.copy(globalConfig = self.globalConfig.updated(configFieldName, config))

def withHighlight(fieldName: String, fieldConfig: HighlightConfig = Map.empty): Highlights =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need Field here also? And maybe use field instead of fieldName.
Alos, I would use config instead of fieldConfig.

case class Highlights(fields: Chunk[HighlightField], globalConfig: HighlightConfig = Map.empty) { self =>
def toJson: Json = Obj("highlight" -> Obj(configList: _*).merge(fieldsList))

def withGlobalConfig(configFieldName: String, config: Json): Highlights =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use field here as well.

type HighlightConfig = Map[String, Json]
}

case class HighlightField(fieldName: String, fieldConfig: HighlightConfig = Map.empty) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use field and config?
Also, we are missing final.

case (Some(s), Some(h)) => r.query.toJson merge s merge h
case (Some(s), _) => r.query.toJson merge s
case (_, Some(h)) => r.query.toJson merge h
case _ => r.query.toJson
Copy link
Contributor

@arnoldlacko arnoldlacko Apr 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use explicit None (when _ only stands for None or (None, None)), so that cases could be easily reordered without changing the meaning.

@markaya markaya force-pushed the dsl-support-highlights branch from b442cbd to 654a79f Compare April 3, 2023 11:42
@@ -311,16 +319,29 @@ object ElasticRequest {
with HasRouting[SearchRequest]
with WithSort[SearchRequest] {
def aggregate(aggregation: ElasticAggregation): SearchAndAggregateRequest
def highlights(value: Highlights): Search
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a new line before?

@@ -360,7 +364,10 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig
case HttpOk =>
response.body.fold(
e => ZIO.fail(new ElasticException(s"Exception occurred: ${e.getMessage}")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move => ZIO.fail to new line as well.

@@ -463,7 +470,15 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig
case HttpOk =>
response.body.fold(
e => ZIO.fail(new ElasticException(s"Exception occurred: ${e.getMessage}")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

}

final case class HighlightField(field: String, config: HighlightConfig = Map.empty) {
def toStringJsonPair: (String, Obj) = field -> Obj(config.toList: _*)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this visible to the user?


def withExplicitFieldOrder: Highlights = self.copy(explicitFieldOrder = true)

private def configList: List[(String, Json)] = config.toList
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a new line between. Can we use lazy val instead?

def documentAs[A](implicit schema: Schema[A]): Either[DecodeError, A] = JsonDecoder.decode(schema, raw.toString)

lazy val highlights: Option[Map[String, Chunk[String]]] = highlight.flatMap { json =>
json.toString.fromJson[Map[String, Chunk[String]]] match {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use .toOption only?

@@ -63,6 +63,8 @@ final class SearchResult private[elasticsearch] (private val hits: List[Item]) e
DecodingException(s"Could not parse all documents successfully: ${errors.map(_.message).mkString(",")})")
}
}

def items: ZIO[Any, Nothing, List[Item]] = ZIO.succeed(hits)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use alias for ZIO[Any, Nothing, A].

config: HighlightConfig = Map.empty,
explicitFieldOrder: Boolean = false
) { self =>
def toJson: Json = Obj("highlight" -> Obj(configList: _*).merge(fieldsList))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use private[elasticsearch] here at least.

config: HighlightConfig = Map.empty,
explicitFieldOrder: Boolean = false
) { self =>
def withExplicitFieldOrder: Highlights = self.copy(explicitFieldOrder = true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this to the new line?

@markaya markaya force-pushed the dsl-support-highlights branch from c0a5599 to ef89dca Compare April 4, 2023 10:11
@@ -549,6 +553,158 @@ object HttpExecutorSpec extends IntegrationSpec {
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
)
) @@ shrinks(0),
suite("searching for documents with highlights")(
test("successfully find document and return highlight") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe return document and highlight/with highlight?

Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("successfully find document and return highlight using field accessor") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("successfully find document and return highlights map") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("successfully find document and use global config to return highlight") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe return document and highlight using global config?

Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("successfully find document and use local config to overwrite global config and return highlight") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same?

* limitations under the License.
*/

package zio.elasticsearch.highlighting
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just highlight?

Comment on lines 39 to 40
def withHighlight(field: Field[_, _]): Highlights =
withHighlight(field.toString, Map.empty)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Aggregations and Queries order of methods was like this:
method(f: Field[_, _])
method(f: String),
so maybe we could do same here?


private lazy val configList: List[(String, Json)] = config.toList

private lazy val fieldsList: Obj =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have configList: List[(String, String)] above, and here fieldsList: Obj.
Maybe we should call this fieldsListJson?

Comment on lines 424 to 436
def toJson: Json = {
val baseJson = (self.from, self.size) match {
case (Some(from), Some(size)) =>
Obj("from" -> from.toJson) merge Obj("size" -> size.toJson) merge self.query.toJson
case (Some(from), None) =>
Obj("from" -> from.toJson) merge self.query.toJson
case (None, Some(size)) =>
Obj("size" -> size.toJson) merge self.query.toJson
case _ =>
self.query.toJson
}
val fromJson: Json = self.from.map(f => Obj("from" -> f.toJson)).getOrElse(Obj())

sortBy match {
case sorts if sorts.nonEmpty =>
baseJson merge Obj("sort" -> Arr(self.sortBy.toList.map(_.paramsToJson): _*)) merge aggregation.toJson
case _ =>
baseJson merge aggregation.toJson
}
val sizeJson: Json = self.size.map(s => Obj("size" -> s.toJson)).getOrElse(Obj())

val highlightsJson: Json = self.highlights.map(_.toJson).getOrElse(Obj())

val sortJson: Json =
if (self.sortBy.nonEmpty) Obj("sort" -> Arr(self.sortBy.toList.map(_.paramsToJson): _*)) else Obj()

fromJson merge sizeJson merge highlightsJson merge sortJson merge self.query.toJson
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing aggregations here.

Comment on lines 174 to 175
_ = println(docs)
_ = println(aggs)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove prints

dbulaja98
dbulaja98 previously approved these changes Apr 4, 2023
@drmarjanovic drmarjanovic merged commit 3d2998c into main Apr 4, 2023
@drmarjanovic drmarjanovic deleted the dsl-support-highlights branch April 4, 2023 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants