-
Notifications
You must be signed in to change notification settings - Fork 73
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
Find select field #99
Comments
You have two options:
val members: List<SLPlayerId> = Settlement.COL
.withDocumentClass<Document>()
.find(Settlement::nation eq id)
.projection(Settlement::members)
.map { it.getString(Settlement::members.name) }
.flatten() This will not work if
data class SettlementWithMembersOnly(val members: Array<Array<SLPlayerId>>)
val members: List<SLPlayerId> = Settlement.COL
.withDocumentClass<SettlementWithMembersOnly>()
.find(Settlement::nation eq id)
.projection(Settlement::members)
.map { it.members }
.flatten() Also I'm going to add a projection extension method, in order to project "out of the box" one, two or three fields. HTH |
Members is just a set of IDs so that'll work, thanks. Should I leave the issue open for the addition or close it? |
Also, is there a slack or somewhere better to ask questions? |
Okay... I made a generic utility for getting specific values, will this work? fun <T> MongoCollection<T>.getValues(id: Any, vararg properties: KProperty<*>): Map<KProperty<*>, Any> {
val map: MutableMap<KProperty<*>, Any> = mutableMapOf()
val results: FindIterable<Document> = this.withDocumentClass<Document>()
.find(Filters.eq("_id", id))
.projection(*properties)
for (document: Document in results) {
for (property: KProperty<*> in properties) {
val path: String = property.path()
val value: Any = document[path] ?: error("Missing value for path $path")
map[property] = value
}
}
return map
}
@Suppress("UNCHECKED_CAST")
fun <T> Map<KProperty<*>, *>.getProperty(property: KProperty<T>): T = getValue(property) as T Used like this: fun getName(settlementId: Id<Settlement>): String? {
return Settlement.COL.getValues(settlementId, Settlement::name).getProperty(Settlement::name)
} |
Actually.. that wouldn't work with anything more complex than strings/numbers. Maybe this instead?: inline fun <reified R> Map<KProperty<*>, *>.getProperty(property: KProperty<R>): R {
val value: Any = get(property) ?: error("Property ${property.path()} not in collection")
return value as R
}
inline fun <reified I, reified R> Map<KProperty<*>, *>.convertProperty(property: KProperty<R>, convert: (I) -> R): R {
return convert.invoke(getProperty(property) as I)
} Uses: fun getName(settlementId: Id<Settlement>): String? = Settlement.COL
.getValues(settlementId, Settlement::name)
.getProperty(Settlement::name)
fun getLeader(settlementId: Id<Settlement>): Id<SLPlayer>? = Settlement.COL
.getValues(settlementId, Settlement::leader)
.convertProperty(Settlement::leader) { objectId: ObjectId -> objectId.toId() } |
https://gist.github.com/c76df079bbc16fd318da551ef7e256f1 bit cleaner version, instead of using the confusing map class it extends LinkedHashMap to be ProjectedResults EDIT: Updated it a lot, it's much improved over the original and very flexible |
to ask questions use gitter https://gitter.im/kmongoo/Lobby or google groups https://groups.google.com/forum/#!forum/kmongo Your solution is interesting but will not work with complex objects. I'm going to provide a patch tomorrow (so keep open this ticket). Thanks |
Okay, hopefully you'll find what I came up with helpful :) |
I have nations with settlements with members, I'm trying to get all of the members of the nation through the settlements.
This gives me this error:
Is there a way to get the value without attempting to construct the whole object?
The text was updated successfully, but these errors were encountered: