add Parser

This commit is contained in:
tursom 2020-02-27 04:14:46 +08:00
parent 4a9e3024ca
commit 32dea366e9
8 changed files with 273 additions and 4 deletions

View File

@ -0,0 +1,109 @@
package cn.tursom.mongodb
import com.mongodb.MongoNamespace
import com.mongodb.client.model.*
import org.bson.conversions.Bson
import kotlin.reflect.KProperty1
@Suppress("unused")
object Aggregate {
operator fun invoke(action: Aggregate.() -> Bson) = this.action()
fun addFields(vararg fields: Field<*>): Bson = Aggregates.addFields(fields.asList())
fun addFields(fields: List<Field<*>>): Bson? = Aggregates.addFields(fields)
fun <TExpression, Boundary> bucket(
groupBy: TExpression,
boundaries: List<Boundary>
): Bson = Aggregates.bucket(groupBy, boundaries)
fun <TExpression, TBoundary> bucket(
groupBy: TExpression,
boundaries: List<TBoundary>,
options: BucketOptions
): Bson = Aggregates.bucket(groupBy, boundaries, options)
fun <TExpression> bucketAuto(groupBy: TExpression, buckets: Int): Bson = Aggregates.bucketAuto(groupBy, buckets)
fun <TExpression> bucketAuto(
groupBy: TExpression,
buckets: Int,
options: BucketAutoOptions
): Bson = Aggregates.bucketAuto(groupBy, buckets, options)
fun count(): Bson = Aggregates.count()
fun count(field: String): Bson = Aggregates.count(field)
fun match(filter: Bson): Bson = Aggregates.match(filter)
fun match(value: Any): Bson = Aggregates.match(MongoUtil.convertToBson(value))
fun project(projection: Bson): Bson = Aggregates.project(projection)
fun sort(sort: Bson): Bson = Aggregates.sort(sort)
fun <TExpression> sortByCount(filter: TExpression): Bson = Aggregates.sortByCount(filter)
fun skip(skip: Int): Bson = Aggregates.skip(skip)
fun limit(limit: Int): Bson = Aggregates.limit(limit)
fun lookup(
from: String,
localField: String,
foreignField: String,
`as`: String
): Bson = Aggregates.lookup(from, localField, foreignField, `as`)
fun lookup(from: String, pipeline: List<Bson?>, `as`: String): Bson = Aggregates.lookup(from, pipeline, `as`)
fun <TExpression> lookup(
from: String,
let: List<Variable<TExpression>>? = null,
pipeline: List<Bson>,
`as`: String
): Bson = Aggregates.lookup(from, let, pipeline, `as`)
fun facet(facets: List<Facet>): Bson = Aggregates.facet(facets)
fun facet(vararg facets: Facet): Bson = Aggregates.facet(facets.asList())
fun <TExpression> graphLookup(
from: String,
startWith: TExpression,
connectFromField: String,
connectToField: String,
`as`: String
): Bson = Aggregates.graphLookup(from, startWith, connectFromField, connectToField, `as`)
fun <TExpression> graphLookup(
from: String,
startWith: TExpression,
connectFromField: String,
connectToField: String,
`as`: String,
options: GraphLookupOptions
): Bson = Aggregates.graphLookup(from, startWith, connectFromField, connectToField, `as`, options)
fun <TExpression> group(
id: TExpression? = null,
vararg fieldAccumulators: BsonField
): Bson = Aggregates.group(id, fieldAccumulators.asList())
fun <TExpression> group(
id: TExpression? = null,
fieldAccumulators: List<BsonField>
): Bson = Aggregates.group(id, fieldAccumulators)
fun unwind(field: KProperty1<*, *>): Bson = Aggregates.unwind(MongoUtil.fieldName(field))
fun unwind(field: KProperty1<*, *>, unwindOptions: UnwindOptions): Bson = Aggregates.unwind(MongoUtil.fieldName(field), unwindOptions)
fun unwind(fieldName: String): Bson = Aggregates.unwind(fieldName)
fun unwind(fieldName: String, unwindOptions: UnwindOptions): Bson = Aggregates.unwind(fieldName, unwindOptions)
fun out(collectionName: String): Bson = Aggregates.out(collectionName)
fun merge(collectionName: String): Bson = Aggregates.merge(collectionName)
fun merge(namespace: MongoNamespace): Bson = Aggregates.merge(namespace)
fun merge(collectionName: String, options: MergeOptions): Bson = Aggregates.merge(collectionName, options)
fun merge(namespace: MongoNamespace, options: MergeOptions): Bson = Aggregates.merge(namespace, options)
fun <TExpression> replaceRoot(value: TExpression): Bson = Aggregates.replaceRoot(value)
fun <TExpression> replaceWith(value: TExpression): Bson = Aggregates.replaceWith(value)
fun sample(size: Int): Bson = Aggregates.sample(size)
}

View File

@ -2,6 +2,7 @@ package cn.tursom.mongodb
import cn.tursom.core.*
import cn.tursom.mongodb.annotation.Ignore
import com.mongodb.client.AggregateIterable
import com.mongodb.client.FindIterable
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
@ -70,6 +71,7 @@ class MongoOperator<T : Any>(
fun list(where: Bson? = null): List<T> {
val find = find(where)
val iterator = find.iterator()
return find.mapNotNull { Parser.parse(it, clazz) }
}
@ -81,6 +83,24 @@ class MongoOperator<T : Any>(
}
}
fun get(filter: Bson? = null): Iterable<T> {
val result = if (filter != null) {
collection.find(filter)
} else {
collection.find()
}
return object : Iterable<T> {
override fun iterator(): Iterator<T> = object : Iterator<T> {
val iterator = result.iterator()
override fun hasNext(): Boolean = iterator.hasNext()
override fun next(): T = Parser.parse(iterator.next(), clazz)!!
}
}
}
fun aggregate(vararg pipeline: Bson): AggregateIterable<Document> = aggregate(pipeline.asList())
private fun convertToBson(entity: Any): Document {
val bson = Document()
fields.forEach {
@ -97,8 +117,7 @@ class MongoOperator<T : Any>(
}.cast<T>()
fields.forEach {
val value = bson[MongoUtil.fieldName(it)] ?: return@forEach
MongoUtil.injectValue(bson, it.get(entity) ?: return@forEach, it)
MongoUtil.injectValue(bson, value, it)
}
return entity
}

View File

@ -0,0 +1,40 @@
package cn.tursom.mongodb
import com.mongodb.client.model.Projections
import org.bson.conversions.Bson
import kotlin.reflect.KProperty1
object Projection {
operator fun invoke(action: Projection.() -> Bson) = this.action()
fun <T, TExpression> computed(field: KProperty1<out T, *>, expression: TExpression): Bson = computed(MongoUtil.fieldName(field), expression)
fun <TExpression> computed(fieldName: String, expression: TExpression): Bson = Projections.computed(fieldName, expression)
fun <T> include(vararg fieldNames: KProperty1<out T, *>): Bson = Projections.include(fieldNames.map { MongoUtil.fieldName(it) })
fun <T> include(fieldNames: Collection<KProperty1<out T, *>>): Bson = Projections.include(fieldNames.map { MongoUtil.fieldName(it) })
fun include(vararg fieldNames: String): Bson = Projections.include(fieldNames.asList())
fun include(fieldNames: List<String>): Bson = Projections.include(fieldNames)
fun <T> exclude(vararg fieldNames: KProperty1<out T, *>): Bson = Projections.exclude(fieldNames.map { MongoUtil.fieldName(it) })
fun <T> exclude(fieldNames: Collection<KProperty1<out T, *>>): Bson = Projections.exclude(fieldNames.map { MongoUtil.fieldName(it) })
fun exclude(vararg fieldNames: String): Bson = Projections.exclude(fieldNames.asList())
fun exclude(fieldNames: List<String>): Bson = Projections.exclude(fieldNames)
fun excludeId(): Bson = Projections.excludeId()
fun <T> exclude(field: KProperty1<out T, *>): Bson = Projections.elemMatch(MongoUtil.fieldName(field))
fun <T> exclude(field: KProperty1<out T, *>, filter: Bson): Bson = Projections.elemMatch(MongoUtil.fieldName(field), filter)
fun elemMatch(fieldName: String): Bson = Projections.elemMatch(fieldName)
fun elemMatch(fieldName: String, filter: Bson): Bson = Projections.elemMatch(fieldName, filter)
fun <T> metaTextScore(field: KProperty1<out T, *>): Bson = Projections.metaTextScore(MongoUtil.fieldName(field))
fun metaTextScore(fieldName: String): Bson = Projections.metaTextScore(fieldName)
fun <T> slice(field: KProperty1<out T, *>, limit: Int): Bson = Projections.slice(MongoUtil.fieldName(field), limit)
fun <T> slice(field: KProperty1<out T, *>, skip: Int, limit: Int): Bson = Projections.slice(MongoUtil.fieldName(field), skip, limit)
fun slice(fieldName: String, limit: Int): Bson = Projections.slice(fieldName, limit)
fun slice(fieldName: String, skip: Int, limit: Int): Bson = Projections.slice(fieldName, skip, limit)
fun fields(vararg projections: Bson): Bson = Projections.fields(projections.asList())
fun fields(projections: List<Bson>): Bson = Projections.fields(projections)
}

View File

@ -0,0 +1,22 @@
package cn.tursom.mongodb
import com.mongodb.client.model.Sorts
import org.bson.conversions.Bson
import kotlin.reflect.KProperty1
object Sort {
operator fun invoke(action: Sort.() -> Bson) = this.action()
fun <T> ascending(vararg fieldNames: KProperty1<out T, *>): Bson = Sorts.ascending(fieldNames.map { MongoUtil.fieldName(it) })
fun <T> ascending(fieldNames: Collection<KProperty1<out T, *>>): Bson = Sorts.ascending(fieldNames.map { MongoUtil.fieldName(it) })
fun ascending(vararg fieldNames: String): Bson = Sorts.ascending(fieldNames.asList())
fun ascending(fieldNames: List<String>): Bson = Sorts.ascending(fieldNames)
fun <T> descending(vararg fieldNames: KProperty1<out T, *>): Bson = Sorts.descending(fieldNames.map { MongoUtil.fieldName(it) })
fun <T> descending(fieldNames: Collection<KProperty1<out T, *>>): Bson = Sorts.descending(fieldNames.map { MongoUtil.fieldName(it) })
fun descending(vararg fieldNames: String): Bson = Sorts.descending(fieldNames.asList())
fun descending(fieldNames: List<String>): Bson = Sorts.descending(fieldNames)
fun <T> KProperty1<out T, *>.metaTextScore(): Bson = Sorts.metaTextScore(MongoUtil.fieldName(this))
fun metaTextScore(fieldName: String): Bson = Sorts.metaTextScore(fieldName)
fun orderBy(vararg sorts: Bson): Bson = Sorts.orderBy(sorts.asList())
fun orderBy(sorts: List<Bson>): Bson = Sorts.orderBy(sorts)
}

View File

@ -0,0 +1,5 @@
package cn.tursom
fun main() {
}

View File

@ -0,0 +1,74 @@
package cn.tursom.core.datastruct
interface AbstractList<T> : List<T> {
override fun contains(element: T): Boolean {
forEach {
if (it == element) {
return true
}
}
return false
}
override fun containsAll(elements: Collection<T>): Boolean {
elements.forEach {
if (!contains(it)) return false
}
return true
}
override fun get(index: Int): T {
forEachIndexed { i, t ->
if (index == i) {
return t
}
}
throw IndexOutOfBoundsException()
}
override fun indexOf(element: T): Int {
forEachIndexed { i, t ->
if (t == element) {
return i
}
}
return -1
}
override fun isEmpty(): Boolean {
return size == 0
}
override fun iterator(): Iterator<T> = listIterator()
override fun lastIndexOf(element: T): Int {
var lastIndex = -1
forEachIndexed { i, t ->
if (t == element) {
lastIndex = i
}
}
return lastIndex
}
override fun listIterator(): ListIterator<T> = listIterator(0)
override fun subList(fromIndex: Int, toIndex: Int): List<T> = SubList(this, fromIndex, toIndex)
}
class SubList<T>(val list: List<T>, val fromIndex: Int, val toIndex: Int) : AbstractList<T> {
override val size: Int = toIndex - fromIndex
override fun listIterator(index: Int): ListIterator<T> = object : ListIterator<T> {
var i: Int = index - 1
override fun hasPrevious(): Boolean = i > 0
override fun previousIndex(): Int = i - 1
override fun previous(): T = this@SubList[--i]
override fun hasNext(): Boolean = i < this@SubList.size
override fun nextIndex(): Int = i + 1
override fun next(): T = this@SubList[++i]
}
}

View File

@ -9,7 +9,7 @@ interface AbstractMutableList<T> : MutableList<T> {
}
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> {
return SubList(this, fromIndex, toIndex)
return MutableSubList(this, fromIndex, toIndex)
}
override fun clear() {

View File

@ -1,6 +1,6 @@
package cn.tursom.core.datastruct
class SubList<T>(
class MutableSubList<T>(
val parent: MutableList<T>,
val fromIndex: Int,
val toIndex: Int