-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
59f07da
commit b5a2721
Showing
4 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
...in/kotlin/com/github/inflab/spring/data/mongodb/core/aggregation/ExtendedSortOperation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.github.inflab.spring.data.mongodb.core.aggregation | ||
|
||
import org.bson.Document | ||
import org.springframework.data.mongodb.core.aggregation.AggregationOperation | ||
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext | ||
|
||
class ExtendedSortOperation : AggregationOperation { | ||
private val document: Document = Document() | ||
|
||
fun ascending(field: String) { | ||
document[field] = 1 | ||
} | ||
|
||
fun descending(field: String) { | ||
document[field] = -1 | ||
} | ||
|
||
fun textScore(field: String) { | ||
document[field] = Document("\$meta", "textScore") | ||
} | ||
|
||
@Deprecated("Deprecated in Java") | ||
override fun toDocument(context: AggregationOperationContext) = | ||
Document(operator, document) | ||
|
||
override fun getOperator(): String = "\$sort" | ||
} |
64 changes: 64 additions & 0 deletions
64
core/src/main/kotlin/com/github/inflab/spring/data/mongodb/core/aggregation/SortStageDsl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.github.inflab.spring.data.mongodb.core.aggregation | ||
|
||
import com.github.inflab.spring.data.mongodb.core.annotation.AggregationMarker | ||
import com.github.inflab.spring.data.mongodb.core.extension.toDotPath | ||
import kotlin.reflect.KProperty | ||
|
||
/** | ||
* A Kotlin DSL to configure $sort stage using idiomatic Kotlin code. | ||
* | ||
* @author Jake Son | ||
* @since 1.0 | ||
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/sort">$sort (aggregation)</a> | ||
*/ | ||
@AggregationMarker | ||
class SortStageDsl { | ||
private val operation = ExtendedSortOperation() | ||
|
||
enum class Order { | ||
Ascending, | ||
Descending, | ||
TextScore, | ||
} | ||
|
||
/** | ||
* Sort ascending. | ||
*/ | ||
val Ascending: Order = Order.Ascending | ||
|
||
/** | ||
* Sort descending. | ||
*/ | ||
val Descending: Order = Order.Descending | ||
|
||
/** | ||
* Sort by the computed `textScore` metadata in descending order. | ||
* | ||
* @see <a href="https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort/#std-label-sort-pipeline-metadata">Text Score Metadata Sort</a> | ||
*/ | ||
val TextScore: Order = Order.TextScore | ||
|
||
/** | ||
* Specifies the field to sort by. | ||
* | ||
* @param order The order to sort by. | ||
*/ | ||
infix fun String.by(order: Order): Boolean { | ||
when (order) { | ||
Order.Ascending -> operation.ascending(this) | ||
Order.Descending -> operation.descending(this) | ||
Order.TextScore -> operation.textScore(this) | ||
} | ||
return true | ||
} | ||
|
||
/** | ||
* Specifies the field to sort by. | ||
* | ||
* @param order The order to sort by. | ||
*/ | ||
infix fun KProperty<*>.by(order: Order): Boolean = | ||
this.toDotPath() by order | ||
|
||
internal fun get() = operation | ||
} |
160 changes: 160 additions & 0 deletions
160
...rc/test/kotlin/com/github/inflab/spring/data/mongodb/core/aggregation/SortStageDslTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package com.github.inflab.spring.data.mongodb.core.aggregation | ||
|
||
import com.github.inflab.spring.data.mongodb.core.mapping.rangeTo | ||
import com.github.inflab.spring.data.mongodb.core.util.shouldBeJson | ||
import io.kotest.core.spec.style.FreeSpec | ||
|
||
internal class SortStageDslTest : FreeSpec({ | ||
fun sort(block: SortStageDsl.() -> Unit) = | ||
SortStageDsl().apply(block) | ||
|
||
"ascending" - { | ||
"should add a field by string" { | ||
// given | ||
val stage = sort { | ||
"field" by Ascending | ||
} | ||
|
||
// when | ||
val result = stage.get() | ||
|
||
// then | ||
result.shouldBeJson( | ||
""" | ||
{ | ||
"${'$'}sort": { | ||
"field": 1 | ||
} | ||
} | ||
""".trimIndent(), | ||
) | ||
} | ||
|
||
"should add a field by property" { | ||
// given | ||
data class Child(val field: String) | ||
data class Parent(val child: Child, val parentField: String) | ||
val stage = sort { | ||
Parent::child..Child::field by Ascending | ||
Parent::parentField by Ascending | ||
} | ||
|
||
// when | ||
val result = stage.get() | ||
|
||
// then | ||
result.shouldBeJson( | ||
""" | ||
{ | ||
"${'$'}sort": { | ||
"child.field": 1, | ||
"parentField": 1 | ||
} | ||
} | ||
""".trimIndent(), | ||
) | ||
} | ||
} | ||
|
||
"descending" - { | ||
"should add a field by string" { | ||
// given | ||
val stage = sort { | ||
"field" by Descending | ||
} | ||
|
||
// when | ||
val result = stage.get() | ||
|
||
// then | ||
result.shouldBeJson( | ||
""" | ||
{ | ||
"${'$'}sort": { | ||
"field": -1 | ||
} | ||
} | ||
""".trimIndent(), | ||
) | ||
} | ||
|
||
"should add a field by property" { | ||
// given | ||
data class Child(val field: String) | ||
data class Parent(val child: Child, val parentField: String) | ||
val stage = sort { | ||
Parent::child..Child::field by Descending | ||
Parent::parentField by Descending | ||
} | ||
|
||
// when | ||
val result = stage.get() | ||
|
||
// then | ||
result.shouldBeJson( | ||
""" | ||
{ | ||
"${'$'}sort": { | ||
"child.field": -1, | ||
"parentField": -1 | ||
} | ||
} | ||
""".trimIndent(), | ||
) | ||
} | ||
} | ||
|
||
"textScore" - { | ||
"should add a field by string" { | ||
// given | ||
val stage = sort { | ||
"field" by TextScore | ||
} | ||
|
||
// when | ||
val result = stage.get() | ||
|
||
// then | ||
result.shouldBeJson( | ||
""" | ||
{ | ||
"${'$'}sort": { | ||
"field": { | ||
"${'$'}meta": "textScore" | ||
} | ||
} | ||
} | ||
""".trimIndent(), | ||
) | ||
} | ||
|
||
"should add a field by property" { | ||
// given | ||
data class Child(val field: String) | ||
data class Parent(val child: Child, val parentField: String) | ||
val stage = sort { | ||
Parent::child..Child::field by TextScore | ||
Parent::parentField by TextScore | ||
} | ||
|
||
// when | ||
val result = stage.get() | ||
|
||
// then | ||
result.shouldBeJson( | ||
""" | ||
{ | ||
"${'$'}sort": { | ||
"child.field": { | ||
"${'$'}meta": "textScore" | ||
}, | ||
"parentField": { | ||
"${'$'}meta": "textScore" | ||
} | ||
} | ||
} | ||
""".trimIndent(), | ||
) | ||
} | ||
} | ||
}) |