From ba493f7299e31acc6131a84003459356ca29f06f Mon Sep 17 00:00:00 2001 From: Jake Son Date: Thu, 28 Sep 2023 13:51:08 +0900 Subject: [PATCH] test: add geoShape examples --- .../repository/GeoShapeSearchRepository.kt | 139 ++++++++++++++++++ .../GeoShapeSearchRepositoryTest.kt | 64 ++++++++ 2 files changed, 203 insertions(+) create mode 100644 example/spring-data-mongodb/src/main/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepository.kt create mode 100644 example/spring-data-mongodb/src/test/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepositoryTest.kt diff --git a/example/spring-data-mongodb/src/main/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepository.kt b/example/spring-data-mongodb/src/main/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepository.kt new file mode 100644 index 00000000..0687e753 --- /dev/null +++ b/example/spring-data-mongodb/src/main/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepository.kt @@ -0,0 +1,139 @@ +package com.github.inflab.example.spring.data.mongodb.repository + +import com.github.inflab.example.spring.data.mongodb.entity.airbnb.ListingsAndReviews +import com.github.inflab.example.spring.data.mongodb.entity.airbnb.ListingsAndReviewsAddress +import com.github.inflab.spring.data.mongodb.core.aggregation.aggregation +import com.github.inflab.spring.data.mongodb.core.aggregation.search.GeoShapeRelation +import com.github.inflab.spring.data.mongodb.core.mapping.rangeTo +import org.springframework.data.geo.Point +import org.springframework.data.mongodb.core.MongoTemplate +import org.springframework.data.mongodb.core.aggregate +import org.springframework.data.mongodb.core.aggregation.AggregationResults +import org.springframework.data.mongodb.core.geo.GeoJsonMultiPolygon +import org.springframework.data.mongodb.core.geo.GeoJsonPolygon +import org.springframework.stereotype.Repository + +@Repository +class GeoShapeSearchRepository( + private val mongoTemplate: MongoTemplate, +) { + + data class NameAndAddress(val name: String, val address: ListingsAndReviewsAddress) + + /** + * @see Disjoint Example + */ + fun findByDisjoint(): AggregationResults { + val aggregation = aggregation { + search { + geoShape { + relation = GeoShapeRelation.DISJOINT + geometry( + GeoJsonPolygon( + Point(-161.323242, 22.512557), + Point(-152.446289, 22.065278), + Point(-156.09375, 17.811456), + Point(-161.323242, 22.512557), + ), + ) + path(ListingsAndReviews::address..ListingsAndReviewsAddress::location) + } + } + + // TODO: add $limit stage + + project { + excludeId() + +ListingsAndReviews::name + +ListingsAndReviews::address + searchScore() + } + } + + return mongoTemplate.aggregate(aggregation) + } + + /** + * @see Intersects Example + */ + fun findByIntersects(): AggregationResults { + val aggregation = aggregation { + search { + geoShape { + relation = GeoShapeRelation.INTERSECTS + geometry( + GeoJsonMultiPolygon( + listOf( + GeoJsonPolygon( + Point(2.16942, 41.40082), + Point(2.17963, 41.40087), + Point(2.18146, 41.39716), + Point(2.15533, 41.40686), + Point(2.14596, 41.38475), + Point(2.17519, 41.41035), + Point(2.16942, 41.40082), + ), + GeoJsonPolygon( + Point(2.16365, 41.39416), + Point(2.16963, 41.39726), + Point(2.15395, 41.38005), + Point(2.17935, 41.43038), + Point(2.16365, 41.39416), + ), + ), + ), + ) + path(ListingsAndReviews::address..ListingsAndReviewsAddress::location) + } + } + + // TODO: add $limit stage + + project { + excludeId() + +ListingsAndReviews::name + +ListingsAndReviews::address + searchScore() + } + } + + return mongoTemplate.aggregate(aggregation) + } + + /** + * @see Within Example + */ + fun findByWithin(): AggregationResults { + val aggregation = aggregation { + search { + geoShape { + relation = GeoShapeRelation.WITHIN + geometry( + GeoJsonPolygon( + Point(-74.3994140625, 40.5305017757), + Point(-74.7290039063, 40.5805846641), + Point(-74.7729492188, 40.9467136651), + Point(-74.0698242188, 41.1290213475), + Point(-73.65234375, 40.9964840144), + Point(-72.6416015625, 40.9467136651), + Point(-72.3559570313, 40.7971774152), + Point(-74.3994140625, 40.5305017757), + ), + ) + path(ListingsAndReviews::address..ListingsAndReviewsAddress::location) + } + } + + // TODO: add $limit stage + + project { + excludeId() + +ListingsAndReviews::name + +ListingsAndReviews::address + searchScore() + } + } + + return mongoTemplate.aggregate(aggregation) + } +} diff --git a/example/spring-data-mongodb/src/test/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepositoryTest.kt b/example/spring-data-mongodb/src/test/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepositoryTest.kt new file mode 100644 index 00000000..a168a79c --- /dev/null +++ b/example/spring-data-mongodb/src/test/kotlin/com/github/inflab/example/spring/data/mongodb/repository/GeoShapeSearchRepositoryTest.kt @@ -0,0 +1,64 @@ +package com.github.inflab.example.spring.data.mongodb.repository + +import com.github.inflab.example.spring.data.mongodb.extension.AtlasTest +import io.kotest.core.annotation.Ignored +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe + +@Ignored +@AtlasTest(database = "sample_airbnb") +internal class GeoShapeSearchRepositoryTest( + private val geoShapeSearchRepository: GeoShapeSearchRepository, +) : FreeSpec({ + + "findByDisjoint" { + // when + val result = geoShapeSearchRepository.findByDisjoint() + + // then + result.mappedResults.take(3).map { it.name } shouldBe listOf( + "Ribeira Charming Duplex", + "Horto flat with small garden", + "Private Room in Bushwick", + ) + result.mappedResults.take(3).map { it.address.location.coordinates } shouldBe listOf( + listOf(-8.61308, 41.1413), + listOf(-43.23074991429229, -22.966253551739655), + listOf(-73.93615, 40.69791), + ) + } + + "findByIntersects" { + // when + val result = geoShapeSearchRepository.findByIntersects() + + // then + result.mappedResults.take(3).map { it.name } shouldBe listOf( + "Cozy bedroom Sagrada Familia", + "", + "SPACIOUS RAMBLA CATALUÑA", + ) + result.mappedResults.take(3).map { it.address.location.coordinates } shouldBe listOf( + listOf(2.17963, 41.40087), + listOf(2.15759, 41.40349), + listOf(2.15255, 41.39193), + ) + } + + "findByWithin" { + // when + val result = geoShapeSearchRepository.findByWithin() + + // then + result.mappedResults.take(3).map { it.name } shouldBe listOf( + "Private Room in Bushwick", + "New York City - Upper West Side Apt", + "Deluxe Loft Suite", + ) + result.mappedResults.take(3).map { it.address.location.coordinates } shouldBe listOf( + listOf(-73.93615, 40.69791), + listOf(-73.96523, 40.79962), + listOf(-73.94472, 40.72778), + ) + } +})