diff --git a/docs/overview/queries/elastic_query_geo_distance.md b/docs/overview/queries/elastic_query_geo_distance.md index d554e554a..427f9a46b 100644 --- a/docs/overview/queries/elastic_query_geo_distance.md +++ b/docs/overview/queries/elastic_query_geo_distance.md @@ -11,50 +11,48 @@ import zio.elasticsearch.query.GeoDistanceQuery import zio.elasticsearch.ElasticQuery._ ``` -You can create a `GeoDistance` query using the `geoDistance` method with latitude and longitude in the following manner: +You can create a `GeoDistance` query using the `geoDistance` method with a GeoPoint in the following manner: ```scala -val query: GeoDistanceQuery = geoDistance(field = "location", latitude = 20.0, longitude = 20.0) +val query: GeoDistanceQuery = + geoDistance(field = "location", point = GeoPoint(20.0, 20.0), distance = Distance(200, Kilometers)) ``` You can create a [type-safe](https://lambdaworks.github.io/zio-elasticsearch/overview/overview_zio_prelude_schema) `GeoDistance` query using the `geoDistance` method with latitude and longitude in the following manner: ```scala -val query: GeoDistanceQuery = geoDistance(field = Document.location, latitude = 20.0, longitude = 20.0) +val query: GeoDistanceQuery = + geoDistance(field = Document.location, point = GeoPoint(20.0, 20.0), distance = Distance(200, Kilometers)) ``` -You can create a `GeoDistance` query using the `geoDistance` method with coordinates in the following manner: +If you want to specify the `distance_type`, you can use the `distanceType` method: ```scala -val query: GeoDistanceQuery = geoDistance(field = "location", coordinates = "40,31") -``` +import zio.elasticsearch.query.DistanceType -You can create a [type-safe](https://lambdaworks.github.io/zio-elasticsearch/overview/overview_zio_prelude_schema) `GeoDistance` query using the `geoDistance` method with coordinates in the following manner: -```scala -val query: GeoDistanceQuery = geoDistance(field = Document.location, coordinates = "40,31") +val queryWithDistanceType: GeoDistanceQuery = + geoDistance(field = "location", point = GeoPoint(20.0, 20.0), distance = Distance(200, Kilometers)) + .distanceType(value = DistanceType.Plane) ``` -If you want to change the `distance`, you can use `distance` method: +If you want to specify a query name, you can use the `name` method: ```scala -import zio.elasticsearch.query.DistanceUnit - -val queryWithDistance: GeoDistanceQuery = geoDistance(field = "location", coordinates = "40,31").distance(value = 20.0, unit = DistanceUnit.Kilometers) +val queryWithName: GeoDistanceQuery = + geoDistance(field = "location", point = GeoPoint(20.0, 20.0), distance = Distance(200, Kilometers)).name("name") ``` -If you want to change the `distance_type`, you can use `distanceType` method: +If you want to specify the `validation_method`, you can use the `validationMethod` method: ```scala -import zio.elasticsearch.query.DistanceType - -val queryWithDistanceType: GeoDistanceQuery = geoDistance(field = "location", coordinates = "40,31").distanceType(value = DistanceType.Plane) -``` +import zio.elasticsearch.query.ValidationMethod -If you want to change the `_name`, you can use `name` method: -```scala -val queryWithName: GeoDistanceQuery = geoDistance(field = "location", coordinates = "40,31").name("name") +val queryWithValidationMethod: GeoDistanceQuery = + geoDistance(field = "location", point = GeoPoint(20.0, 20.0), distance = Distance(200, Kilometers)) + .validationMethod(value = ValidationMethod.IgnoreMalformed) ``` -If you want to change the `validation_method`, you can use `validationMethod` method: +You can also specify the point as a geo-hash: ```scala import zio.elasticsearch.query.ValidationMethod -val queryWithValidationMethod: GeoDistanceQuery = geoDistance(field = "location", coordinates = "40,31").validationMethod(value = ValidationMethod.IgnoreMalformed) +val queryWithValidationMethod: GeoDistanceQuery = + geoDistance(field = "location", point = GeoHash("drm3btev3e86"), distance = Distance(200, Kilometers)) ``` You can find more information about `GeoDistance` query [here](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-geo-distance-query.html#query-dsl-geo-distance-query). diff --git a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala index 55ecd2b09..8e3c97ec1 100644 --- a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala +++ b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala @@ -22,6 +22,7 @@ import zio.elasticsearch.ElasticHighlight.highlight import zio.elasticsearch.ElasticQuery.{script => _, _} import zio.elasticsearch.ElasticSort.sortBy import zio.elasticsearch.aggregation.AggregationOrder +import zio.elasticsearch.data.GeoPoint import zio.elasticsearch.domain.{PartialTestDocument, TestDocument, TestSubDocument} import zio.elasticsearch.executor.Executor import zio.elasticsearch.query.DistanceUnit.Kilometers @@ -29,7 +30,7 @@ import zio.elasticsearch.query.FunctionScoreFunction.randomScoreFunction import zio.elasticsearch.query.sort.SortMode.Max import zio.elasticsearch.query.sort.SortOrder._ import zio.elasticsearch.query.sort.SourceType.NumberType -import zio.elasticsearch.query.{FunctionScoreBoostMode, FunctionScoreFunction} +import zio.elasticsearch.query.{Distance, FunctionScoreBoostMode, FunctionScoreFunction} import zio.elasticsearch.request.{CreationOutcome, DeletionOutcome} import zio.elasticsearch.result._ import zio.elasticsearch.script.{Painless, Script} @@ -1760,7 +1761,7 @@ object HttpExecutorSpec extends IntegrationSpec { |{ | "mappings": { | "properties": { - | "locationField": { + | "geoPointField": { | "type": "geo_point" | } | } @@ -1774,30 +1775,20 @@ object HttpExecutorSpec extends IntegrationSpec { _ <- Executor.execute( ElasticRequest.create[TestDocument](geoDistanceIndex, document).refreshTrue ) - r1 <- Executor - .execute( - ElasticRequest.search( - geoDistanceIndex, - ElasticQuery - .geoDistance("locationField", document.locationField.lat, document.locationField.lon) - .distance(300, Kilometers) - ) - ) - .documentAs[TestDocument] - r2 <- - Executor - .execute( - ElasticRequest.search( - geoDistanceIndex, - ElasticQuery - .geoDistance("locationField", s"${document.locationField.lat}, ${document.locationField.lon}") - .distance(300, Kilometers) - ) - ) - .documentAs[TestDocument] - } yield assert(r1 ++ r2)( - equalTo(Chunk(document, document)) - ) + result <- Executor + .execute( + ElasticRequest.search( + geoDistanceIndex, + ElasticQuery + .geoDistance( + "geoPointField", + GeoPoint(document.geoPointField.lat, document.geoPointField.lon), + Distance(300, Kilometers) + ) + ) + ) + .documentAs[TestDocument] + } yield assert(result)(equalTo(Chunk(document))) } } @@ after(Executor.execute(ElasticRequest.deleteIndex(geoDistanceIndex)).orDie) ), diff --git a/modules/library/src/it/scala/zio/elasticsearch/IntegrationSpec.scala b/modules/library/src/it/scala/zio/elasticsearch/IntegrationSpec.scala index 78399118f..e330e874e 100644 --- a/modules/library/src/it/scala/zio/elasticsearch/IntegrationSpec.scala +++ b/modules/library/src/it/scala/zio/elasticsearch/IntegrationSpec.scala @@ -19,6 +19,7 @@ package zio.elasticsearch import sttp.client3.httpclient.zio.HttpClientZioBackend import zio._ import zio.elasticsearch.ElasticQuery.matchAll +import zio.elasticsearch.data.GeoPoint import zio.elasticsearch.domain._ import zio.elasticsearch.executor.Executor import zio.test.Assertion.{containsString, hasMessage} @@ -62,11 +63,11 @@ trait IntegrationSpec extends ZIOSpecDefault { def genDocumentId: Gen[Any, DocumentId] = Gen.stringBounded(10, 40)(Gen.alphaNumericChar).map(DocumentId(_)) - def genLocation: Gen[Any, Location] = + def genGeoPoint: Gen[Any, GeoPoint] = for { - latField <- Gen.bigDecimal(10, 90).map(_.setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble) - lonField <- Gen.bigDecimal(10, 90).map(_.setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble) - } yield Location(lat = latField, lon = lonField) + latitude <- Gen.bigDecimal(10, 90).map(_.setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble) + longitude <- Gen.bigDecimal(10, 90).map(_.setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble) + } yield GeoPoint(latitude, longitude) def genTestDocument: Gen[Any, TestDocument] = for { stringField <- Gen.stringBounded(5, 10)(Gen.alphaChar) @@ -75,7 +76,7 @@ trait IntegrationSpec extends ZIOSpecDefault { intField <- Gen.int(1, 2000) doubleField <- Gen.double(100, 2000) booleanField <- Gen.boolean - locationField <- genLocation + geoPointField <- genGeoPoint } yield TestDocument( stringField = stringField, dateField = dateField, @@ -83,7 +84,7 @@ trait IntegrationSpec extends ZIOSpecDefault { intField = intField, doubleField = doubleField, booleanField = booleanField, - locationField = locationField + geoPointField = geoPointField ) def genTestSubDocument: Gen[Any, TestSubDocument] = for { diff --git a/modules/library/src/main/scala/zio/elasticsearch/ElasticQuery.scala b/modules/library/src/main/scala/zio/elasticsearch/ElasticQuery.scala index d379d4cbd..1d88b4964 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/ElasticQuery.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/ElasticQuery.scala @@ -18,6 +18,7 @@ package zio.elasticsearch import zio.Chunk import zio.elasticsearch.ElasticPrimitive.ElasticPrimitive +import zio.elasticsearch.data.GeoPoint import zio.elasticsearch.query._ import zio.elasticsearch.script.Script import zio.schema.Schema @@ -176,25 +177,22 @@ object ElasticQuery { * Constructs a type-safe instance of [[zio.elasticsearch.query.GeoDistanceQuery]] using the specified parameters. * * @param field - * the type-safe field for which query is specified for - * @param longitude - * longitude of the desired point - * @param latitude - * latitude of the desired point + * the type-safe GeoPoint field for which the query is specified + * @param point + * the geo-point from which the distance should be measured + * @param distance + * the distance within which values should be matched * @tparam S - * document for which field query is executed + * the type of document on which the query is defined * @return - * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents `geo_distance` query to be performed. + * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents the `geo_distance` query to be + * performed. */ - final def geoDistance[S]( - field: Field[S, _], - latitude: Double, - longitude: Double - ): GeoDistanceQuery[S] = + final def geoDistance[S](field: Field[S, GeoPoint], point: GeoPoint, distance: Distance): GeoDistanceQuery[S] = GeoDistance( field = field.toString, - point = s"$latitude,$longitude", - distance = None, + point = s"${point.lat},${point.lon}", + distance = distance, distanceType = None, queryName = None, validationMethod = None @@ -204,19 +202,20 @@ object ElasticQuery { * Constructs an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] using the specified parameters. * * @param field - * the field for which query is specified for - * @param longitude - * longitude of the desired point - * @param latitude - * latitude of the desired point + * the field for which the query is specified + * @param point + * the geo-point from which the distance should be measured + * @param distance + * the distance within which values should be matched * @return - * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents `geo_distance` query to be performed. + * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents the `geo_distance` query to be + * performed. */ - final def geoDistance(field: String, latitude: Double, longitude: Double): GeoDistanceQuery[Any] = + final def geoDistance(field: String, point: GeoPoint, distance: Distance): GeoDistanceQuery[Any] = GeoDistance( field = field, - point = s"$latitude,$longitude", - distance = None, + point = s"${point.lat},${point.lon}", + distance = distance, distanceType = None, queryName = None, validationMethod = None @@ -226,20 +225,22 @@ object ElasticQuery { * Constructs a type-safe instance of [[zio.elasticsearch.query.GeoDistanceQuery]] using the specified parameters. * * @param field - * the type-safe field for which query is specified for - * @param coordinates - * longitude and latitude the of the desired point written as string (e.g. "40,31") or geo hash (e.g. - * "drm3btev3e86") + * the type-safe field for which the query is specified + * @param point + * the geo-point from which the distance should be measured, defined as geo-hash + * @param distance + * the distance within which values should be matched * @tparam S - * document for which field query is executed + * the type of document on which the query is defined * @return - * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents `geo_distance` query to be performed. + * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents the `geo_distance` query to be + * performed. */ - final def geoDistance[S](field: Field[S, _], coordinates: String): GeoDistanceQuery[S] = + final def geoDistance[S](field: Field[S, GeoPoint], point: GeoHash, distance: Distance): GeoDistanceQuery[S] = GeoDistance( field = field.toString, - point = coordinates, - distance = None, + point = GeoHash.unwrap(point), + distance = distance, distanceType = None, queryName = None, validationMethod = None @@ -249,17 +250,20 @@ object ElasticQuery { * Constructs an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] using the specified parameters. * * @param field - * the field for which query is specified for - * @param coordinates - * longitude and latitude of the desired point written as string (e.g. "40,31") or geo hash (e.g. "drm3btev3e86") + * the field for which the query is specified + * @param point + * the geo-point from which the distance should be measured, defined as geo-hash + * @param distance + * the distance within which values should be matched * @return - * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents `geo_distance` query to be performed. + * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] that represents the `geo_distance` query to be + * performed. */ - final def geoDistance(field: String, coordinates: String): GeoDistanceQuery[Any] = + final def geoDistance(field: String, point: GeoHash, distance: Distance): GeoDistanceQuery[Any] = GeoDistance( field = field, - point = coordinates, - distance = None, + point = GeoHash.unwrap(point), + distance = distance, distanceType = None, queryName = None, validationMethod = None diff --git a/modules/library/src/main/scala/zio/elasticsearch/data/GeoPoint.scala b/modules/library/src/main/scala/zio/elasticsearch/data/GeoPoint.scala new file mode 100644 index 000000000..826477e1a --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/data/GeoPoint.scala @@ -0,0 +1,25 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.data + +import zio.schema.{DeriveSchema, Schema} + +final case class GeoPoint(lat: Double, lon: Double) + +object GeoPoint { + implicit val schema: Schema.CaseClass2[Double, Double, GeoPoint] = DeriveSchema.gen[GeoPoint] +} diff --git a/modules/library/src/main/scala/zio/elasticsearch/query/GeoHash.scala b/modules/library/src/main/scala/zio/elasticsearch/query/GeoHash.scala new file mode 100644 index 000000000..3c74e3551 --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/query/GeoHash.scala @@ -0,0 +1,21 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.query + +import zio.prelude.Newtype + +object GeoHash extends Newtype[String] diff --git a/modules/library/src/main/scala/zio/elasticsearch/query/Queries.scala b/modules/library/src/main/scala/zio/elasticsearch/query/Queries.scala index 3f064d951..2e59bc317 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/query/Queries.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/query/Queries.scala @@ -333,20 +333,6 @@ private[elasticsearch] final case class FunctionScore[S]( sealed trait GeoDistanceQuery[S] extends ElasticQuery[S] { - /** - * Sets the `distance` parameter for the [[zio.elasticsearch.query.GeoDistanceQuery]]. `Distance` represents the - * radius of the circle centred on the specified location. Points which fall into this circle are considered to be - * matches. The distance can be specified in various units. See [[zio.elasticsearch.query.DistanceUnit]]. - * - * @param value - * a non-negative real number used for the `distance` - * @param unit - * the [[zio.elasticsearch.query.DistanceUnit]] in which we want to represent the distance - * @return - * an instance of [[zio.elasticsearch.query.GeoDistanceQuery]] enriched with the `distance` parameter. - */ - def distance(value: Double, unit: DistanceUnit): GeoDistanceQuery[S] - /** * Sets the `distanceType` parameter for the [[zio.elasticsearch.query.GeoDistanceQuery]]. Defines how to compute the * distance. @@ -390,15 +376,12 @@ sealed trait GeoDistanceQuery[S] extends ElasticQuery[S] { private[elasticsearch] final case class GeoDistance[S]( field: String, point: String, - distance: Option[Distance], + distance: Distance, distanceType: Option[DistanceType], queryName: Option[String], validationMethod: Option[ValidationMethod] ) extends GeoDistanceQuery[S] { self => - def distance(value: Double, unit: DistanceUnit): GeoDistanceQuery[S] = - self.copy(distance = Some(Distance(value, unit))) - def distanceType(value: DistanceType): GeoDistanceQuery[S] = self.copy(distanceType = Some(value)) def name(value: String): GeoDistanceQuery[S] = self.copy(queryName = Some(value)) @@ -409,8 +392,8 @@ private[elasticsearch] final case class GeoDistance[S]( Obj( "geo_distance" -> Obj( Chunk( - Some(field -> point.toJson), - distance.map("distance" -> _.toString.toJson), + Some(field -> point.toJson), + Some("distance" -> distance.toString.toJson), distanceType.map("distance_type" -> _.toString.toJson), queryName.map("_name" -> _.toJson), validationMethod.map("validation_method" -> _.toString.toJson) diff --git a/modules/library/src/main/scala/zio/elasticsearch/query/package.scala b/modules/library/src/main/scala/zio/elasticsearch/query/package.scala new file mode 100644 index 000000000..78e78f1f4 --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/query/package.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch + +package object query { + + type GeoHash = GeoHash.Type + +} diff --git a/modules/library/src/test/scala/zio/elasticsearch/ElasticQuerySpec.scala b/modules/library/src/test/scala/zio/elasticsearch/ElasticQuerySpec.scala index 618a4763d..e8225e433 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/ElasticQuerySpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/ElasticQuerySpec.scala @@ -19,6 +19,7 @@ package zio.elasticsearch import zio.Chunk import zio.elasticsearch.ElasticHighlight.highlight import zio.elasticsearch.ElasticQuery.{script => _, _} +import zio.elasticsearch.data.GeoPoint import zio.elasticsearch.domain._ import zio.elasticsearch.query.DistanceType.Plane import zio.elasticsearch.query.DistanceUnit.Kilometers @@ -551,54 +552,42 @@ object ElasticQuerySpec extends ZIOSpecDefault { ) }, test("geoDistance") { - val query = - geoDistance("testField", 20.0, 21.1) - val queryString = - geoDistance(TestDocument.stringField, "drm3btev3e86") - val queryWithDistance = - geoDistance(TestDocument.stringField, 20.0, 21.1).distance(200, Kilometers) + val queryWithHash = + geoDistance(TestDocument.geoPointField, GeoHash("drm3btev3e86"), Distance(200, Kilometers)) + val queryWithPoint = + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)) val queryWithDistanceType = - geoDistance(TestDocument.stringField, 20.0, 21.1).distanceType(Plane) + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)).distanceType(Plane) val queryWithName = - geoDistance(TestDocument.stringField, 20.0, 21.1).name("name") + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)).name("name") val queryWithValidationMethod = - geoDistance(TestDocument.stringField, 20.0, 21.1).validationMethod(IgnoreMalformed) - val queryWithAllParams = geoDistance(TestDocument.stringField, 20.0, 21.1) - .validationMethod(IgnoreMalformed) - .name("name") - .distanceType(Plane) - .distance(200, Kilometers) - - assert(query)( - equalTo( - GeoDistance[Any]( - field = "testField", - point = "20.0,21.1", - distance = None, - distanceType = None, - queryName = None, - validationMethod = None - ) + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)).validationMethod( + IgnoreMalformed ) - ) && - assert(queryString)( + val queryWithAllParams = + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)) + .validationMethod(IgnoreMalformed) + .distanceType(Plane) + .name("name") + + assert(queryWithHash)( equalTo( GeoDistance[TestDocument]( - field = "stringField", + field = "geoPointField", point = "drm3btev3e86", - distance = None, + distance = Distance(200, Kilometers), distanceType = None, queryName = None, validationMethod = None ) ) ) && - assert(queryWithDistance)( + assert(queryWithPoint)( equalTo( GeoDistance[TestDocument]( - field = "stringField", + field = "geoPointField", point = "20.0,21.1", - distance = Some(Distance(200, Kilometers)), + distance = Distance(200, Kilometers), distanceType = None, queryName = None, validationMethod = None @@ -607,9 +596,9 @@ object ElasticQuerySpec extends ZIOSpecDefault { ) && assert(queryWithDistanceType)( equalTo( GeoDistance[TestDocument]( - field = "stringField", + field = "geoPointField", point = "20.0,21.1", - distance = None, + distance = Distance(200, Kilometers), distanceType = Some(Plane), queryName = None, validationMethod = None @@ -618,9 +607,9 @@ object ElasticQuerySpec extends ZIOSpecDefault { ) && assert(queryWithName)( equalTo( GeoDistance[TestDocument]( - field = "stringField", + field = "geoPointField", point = "20.0,21.1", - distance = None, + distance = Distance(200, Kilometers), distanceType = None, queryName = Some("name"), validationMethod = None @@ -629,9 +618,9 @@ object ElasticQuerySpec extends ZIOSpecDefault { ) && assert(queryWithValidationMethod)( equalTo( GeoDistance[TestDocument]( - field = "stringField", + field = "geoPointField", point = "20.0,21.1", - distance = None, + distance = Distance(200, Kilometers), distanceType = None, queryName = None, validationMethod = Some(IgnoreMalformed) @@ -640,9 +629,9 @@ object ElasticQuerySpec extends ZIOSpecDefault { ) && assert(queryWithAllParams)( equalTo( GeoDistance[TestDocument]( - field = "stringField", + field = "geoPointField", point = "20.0,21.1", - distance = Some(Distance(200, Kilometers)), + distance = Distance(200, Kilometers), distanceType = Some(Plane), queryName = Some("name"), validationMethod = Some(IgnoreMalformed) @@ -1945,38 +1934,30 @@ object ElasticQuerySpec extends ZIOSpecDefault { assert(query.toJson(fieldPath = None))(equalTo(expected.toJson)) }, test("geoDistance") { - val query = - geoDistance("testField", 20.0, 21.1) - val queryString = - geoDistance(TestDocument.locationField, "drm3btev3e86") - val queryWithDistance = - geoDistance(TestDocument.locationField, 20.0, 21.1).distance(200, Kilometers) + val queryWithHash = + geoDistance(TestDocument.geoPointField, GeoHash("drm3btev3e86"), Distance(200, Kilometers)) + val queryWithPoint = + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)) val queryWithDistanceType = - geoDistance(TestDocument.locationField, 20.0, 21.1).distanceType(Plane) + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)).distanceType(Plane) val queryWithName = - geoDistance(TestDocument.locationField, 20.0, 21.1).name("name") + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)).name("name") val queryWithValidationMethod = - geoDistance(TestDocument.locationField, 20.0, 21.1).validationMethod(IgnoreMalformed) - val queryWithAllParams = geoDistance(TestDocument.locationField, 20.0, 21.1) - .validationMethod(IgnoreMalformed) - .distance(200, Kilometers) - .distanceType(Plane) - .name("name") - - val expected = - """ - |{ - | "geo_distance": { - | "testField": "20.0,21.1" - | } - |} - |""".stripMargin + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)).validationMethod( + IgnoreMalformed + ) + val queryWithAllParams = + geoDistance(TestDocument.geoPointField, GeoPoint(20.0, 21.1), Distance(200, Kilometers)) + .validationMethod(IgnoreMalformed) + .distanceType(Plane) + .name("name") - val expectedWithString = + val expectedWithHash = """ |{ | "geo_distance": { - | "locationField": "drm3btev3e86" + | "geoPointField": "drm3btev3e86", + | "distance": "200.0km" | } |} |""".stripMargin @@ -1986,7 +1967,7 @@ object ElasticQuerySpec extends ZIOSpecDefault { |{ | "geo_distance": { | "distance": "200.0km", - | "locationField": "20.0,21.1" + | "geoPointField": "20.0,21.1" | } |} |""".stripMargin @@ -1996,7 +1977,8 @@ object ElasticQuerySpec extends ZIOSpecDefault { |{ | "geo_distance": { | "distance_type" : "plane", - | "locationField": "20.0,21.1" + | "geoPointField": "20.0,21.1", + | "distance": "200.0km" | } |} |""".stripMargin @@ -2006,7 +1988,8 @@ object ElasticQuerySpec extends ZIOSpecDefault { |{ | "geo_distance": { | "_name": "name", - | "locationField": "20.0,21.1" + | "geoPointField": "20.0,21.1", + | "distance": "200.0km" | } |} |""".stripMargin @@ -2016,7 +1999,8 @@ object ElasticQuerySpec extends ZIOSpecDefault { |{ | "geo_distance": { | "validation_method": "IGNORE_MALFORMED", - | "locationField": "20.0,21.1" + | "geoPointField": "20.0,21.1", + | "distance": "200.0km" | } |} |""".stripMargin @@ -2029,14 +2013,13 @@ object ElasticQuerySpec extends ZIOSpecDefault { | "distance_type" : "plane", | "_name": "name", | "distance": "200.0km", - | "locationField": "20.0,21.1" + | "geoPointField": "20.0,21.1" | } |} |""".stripMargin - assert(query.toJson(fieldPath = None))(equalTo(expected.toJson)) && - assert(queryString.toJson(fieldPath = None))(equalTo(expectedWithString.toJson)) && - assert(queryWithDistance.toJson(fieldPath = None))(equalTo(expectedWithDistance.toJson)) && + assert(queryWithHash.toJson(fieldPath = None))(equalTo(expectedWithHash.toJson)) && + assert(queryWithPoint.toJson(fieldPath = None))(equalTo(expectedWithDistance.toJson)) && assert(queryWithDistanceType.toJson(fieldPath = None))(equalTo(expectedWithDistanceType.toJson)) && assert(queryWithName.toJson(fieldPath = None))(equalTo(expectedWithName.toJson)) && assert(queryWithValidationMethod.toJson(fieldPath = None))(equalTo(expectedWithValidationMethod.toJson)) && diff --git a/modules/library/src/test/scala/zio/elasticsearch/ElasticRequestSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/ElasticRequestSpec.scala index 7ca776b83..0e7c4932b 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/ElasticRequestSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/ElasticRequestSpec.scala @@ -5,7 +5,8 @@ import zio.elasticsearch.ElasticAggregation.termsAggregation import zio.elasticsearch.ElasticHighlight.highlight import zio.elasticsearch.ElasticRequest._ import zio.elasticsearch.ElasticSort.sortBy -import zio.elasticsearch.domain.{Location, TestDocument} +import zio.elasticsearch.data.GeoPoint +import zio.elasticsearch.domain.TestDocument import zio.elasticsearch.highlights.{HighlightField, Highlights} import zio.elasticsearch.query.sort.Missing.First import zio.elasticsearch.query.sort.SortByFieldOptions @@ -990,9 +991,9 @@ object ElasticRequestSpec extends ZIOSpecDefault { val expected = """|{ "create" : { "_index" : "index", "routing" : "routing" } } - |{"stringField":"stringField1","subDocumentList":[],"dateField":"2020-10-10","intField":5,"doubleField":7.0,"booleanField":true,"locationField":{"lat":20.0,"lon":21.0}} + |{"stringField":"stringField1","subDocumentList":[],"dateField":"2020-10-10","intField":5,"doubleField":7.0,"booleanField":true,"geoPointField":{"lat":20.0,"lon":21.0}} |{ "index" : { "_index" : "index", "_id" : "documentid" } } - |{"stringField":"stringField2","subDocumentList":[],"dateField":"2022-10-10","intField":10,"doubleField":17.0,"booleanField":false,"locationField":{"lat":10.0,"lon":11.0}} + |{"stringField":"stringField2","subDocumentList":[],"dateField":"2022-10-10","intField":10,"doubleField":17.0,"booleanField":false,"geoPointField":{"lat":10.0,"lon":11.0}} |""".stripMargin assert(requestBody)(equalTo(expected)) @@ -1037,7 +1038,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 5, | "doubleField": 7.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 20.0, | "lon": 21.0 | } @@ -1060,7 +1061,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 5, | "doubleField": 7.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 20.0, | "lon": 21.0 | } @@ -1102,7 +1103,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 5, | "doubleField": 7.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 20.0, | "lon": 21.0 | } @@ -1264,8 +1265,8 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField", | "doubleField", | "booleanField", - | "locationField.lat", - | "locationField.lon" + | "geoPointField.lat", + | "geoPointField.lon" | ] | } |} @@ -1483,7 +1484,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 5, | "doubleField": 7.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 20.0, | "lon": 21.0 | } @@ -1501,7 +1502,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 5, | "doubleField": 7.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 20.0, | "lon": 21.0 | } @@ -1513,7 +1514,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 10, | "doubleField": 17.0, | "booleanField": false, - | "locationField": { + | "geoPointField": { | "lat": 10.0, | "lon": 11.0 | } @@ -1560,7 +1561,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { | "intField": 10, | "doubleField": 17.0, | "booleanField": false, - | "locationField": { + | "geoPointField": { | "lat": 10.0, | "lon": 11.0 | } @@ -1623,7 +1624,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { intField = 5, doubleField = 7.0, booleanField = true, - locationField = Location(20.0, 21.0) + geoPointField = GeoPoint(20.0, 21.0) ) private val Doc2 = TestDocument( stringField = "stringField2", @@ -1632,7 +1633,7 @@ object ElasticRequestSpec extends ZIOSpecDefault { intField = 10, doubleField = 17.0, booleanField = false, - locationField = Location(10.0, 11.0) + geoPointField = GeoPoint(10.0, 11.0) ) private val DocId = DocumentId("documentid") private val Index = IndexName("index") diff --git a/modules/library/src/test/scala/zio/elasticsearch/FunctionScoreSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/FunctionScoreSpec.scala index 24684834a..b9c6edd93 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/FunctionScoreSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/FunctionScoreSpec.scala @@ -137,7 +137,7 @@ object FunctionScoreSpec extends ZIOSpecDefault { .filter(matches("field", "value")) val typeSafeFunction = - linearDecayFunction(TestDocument.locationField, origin = "11, 12", scale = "2km") + linearDecayFunction(TestDocument.geoPointField, origin = "11, 12", scale = "2km") .weight(10.0) .decay(11.0) .multiValueMode(Max) @@ -161,7 +161,7 @@ object FunctionScoreSpec extends ZIOSpecDefault { ) && assert(typeSafeFunction)( equalTo( DecayFunction[TestDocument]( - field = "locationField", + field = "geoPointField", decayFunctionType = Linear, origin = "11, 12", scale = "2km", diff --git a/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala index 08b80bdd0..0568e9018 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala @@ -4,6 +4,7 @@ import sttp.client3.httpclient.zio.HttpClientZioBackend import sttp.client3.testing.SttpBackendStub import sttp.client3.{Request, Response, StringBody} import sttp.model.{Method, StatusCode} +import zio.elasticsearch.data.GeoPoint import zio.elasticsearch.domain._ import zio.elasticsearch.executor.Executor import zio.test.ZIOSpecDefault @@ -42,7 +43,7 @@ trait SttpBackendStubSpec extends ZIOSpecDefault { intField = 10, doubleField = 10.0, booleanField = true, - locationField = Location(1.0, 1.0) + geoPointField = GeoPoint(1.0, 1.0) ) val secondDoc: TestDocument = @@ -53,7 +54,7 @@ trait SttpBackendStubSpec extends ZIOSpecDefault { intField = 12, doubleField = 12.0, booleanField = true, - locationField = Location(1.0, 1.0) + geoPointField = GeoPoint(1.0, 1.0) ) private val url = "http://localhost:9200" @@ -205,7 +206,7 @@ trait SttpBackendStubSpec extends ZIOSpecDefault { | "intField": 10, | "doubleField": 10.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 1.0, | "lon": 1.0 | } @@ -256,7 +257,7 @@ trait SttpBackendStubSpec extends ZIOSpecDefault { | "intField": 10, | "doubleField": 10.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 1.0, | "lon": 1.0 | } @@ -310,7 +311,7 @@ trait SttpBackendStubSpec extends ZIOSpecDefault { | "intField": 10, | "doubleField": 10.0, | "booleanField": true, - | "locationField": { + | "geoPointField": { | "lat": 1.0, | "lon": 1.0 | } diff --git a/modules/library/src/test/scala/zio/elasticsearch/domain/Location.scala b/modules/library/src/test/scala/zio/elasticsearch/domain/Location.scala deleted file mode 100644 index 87e520c9a..000000000 --- a/modules/library/src/test/scala/zio/elasticsearch/domain/Location.scala +++ /dev/null @@ -1,12 +0,0 @@ -package zio.elasticsearch.domain - -import zio.elasticsearch.FieldAccessorBuilder -import zio.schema.{DeriveSchema, Schema} - -final case class Location(lat: Double, lon: Double) - -object Location { - implicit val schema: Schema.CaseClass2[Double, Double, Location] = DeriveSchema.gen[Location] - - val (latField, lonField) = schema.makeAccessors(FieldAccessorBuilder) -} diff --git a/modules/library/src/test/scala/zio/elasticsearch/domain/TestDocument.scala b/modules/library/src/test/scala/zio/elasticsearch/domain/TestDocument.scala index 11713f067..b7f6fe8e7 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/domain/TestDocument.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/domain/TestDocument.scala @@ -1,6 +1,7 @@ package zio.elasticsearch.domain import zio.elasticsearch.FieldAccessorBuilder +import zio.elasticsearch.data.GeoPoint import zio.schema.{DeriveSchema, Schema} import java.time.LocalDate @@ -12,14 +13,14 @@ final case class TestDocument( intField: Int, doubleField: Double, booleanField: Boolean, - locationField: Location + geoPointField: GeoPoint ) object TestDocument { implicit val schema - : Schema.CaseClass7[String, List[TestSubDocument], LocalDate, Int, Double, Boolean, Location, TestDocument] = + : Schema.CaseClass7[String, List[TestSubDocument], LocalDate, Int, Double, Boolean, GeoPoint, TestDocument] = DeriveSchema.gen[TestDocument] - val (stringField, subDocumentList, dateField, intField, doubleField, booleanField, locationField) = + val (stringField, subDocumentList, dateField, intField, doubleField, booleanField, geoPointField) = schema.makeAccessors(FieldAccessorBuilder) }