diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/FieldLookup.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/FieldLookup.kt similarity index 97% rename from vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/FieldLookup.kt rename to vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/FieldLookup.kt index 0bbdd616..68ded10a 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/FieldLookup.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/FieldLookup.kt @@ -1,4 +1,4 @@ -package org.vitrivr.engine.query.transform +package org.vitrivr.engine.query.transform.lookup import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/FieldLookupFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/FieldLookupFactory.kt similarity index 94% rename from vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/FieldLookupFactory.kt rename to vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/FieldLookupFactory.kt index 6e6ae45d..08c53884 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/FieldLookupFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/FieldLookupFactory.kt @@ -1,4 +1,4 @@ -package org.vitrivr.engine.query.transform +package org.vitrivr.engine.query.transform.lookup import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.Retrieved diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/ObjectFieldLookup.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/ObjectFieldLookup.kt new file mode 100644 index 00000000..37ff87a6 --- /dev/null +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/ObjectFieldLookup.kt @@ -0,0 +1,50 @@ +package org.vitrivr.engine.query.transform.lookup + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.toList +import org.vitrivr.engine.core.database.descriptor.DescriptorReader +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.retrievable.Relationship +import org.vitrivr.engine.core.model.retrievable.Retrieved +import org.vitrivr.engine.core.model.retrievable.attributes.DescriptorAttribute +import org.vitrivr.engine.core.model.retrievable.attributes.RelationshipAttribute +import org.vitrivr.engine.core.operators.Operator +import org.vitrivr.engine.core.operators.retrieve.Transformer + +/** + * Appends [DescriptorAttribute] to a [Retrieved] in a specified object [Relationship] based on lookup values of a [Schema.Field], if available. + * + * @version 1.0.0 + * @author Luca Rossetto + * @author Ralph Gasser + */ +class ObjectFieldLookup(override val input: Operator, private val reader: DescriptorReader<*>, private val predicates: Set) : Transformer { + override fun toFlow(scope: CoroutineScope): Flow = flow { + /* Parse input IDs.*/ + val inputRetrieved = input.toFlow(scope).toList() + + /* Fetch Retrievable entries that should be enriched. */ + val enrich = inputRetrieved.mapNotNull { it.filteredAttribute(RelationshipAttribute::class.java) }.flatMap { r -> + r.relationships.filter { this@ObjectFieldLookup.predicates.isEmpty() || it.pred in this@ObjectFieldLookup.predicates }.mapNotNull { it.obj.second } + } + val ids = enrich.map { it.id } + val descriptors = if (ids.isNotEmpty()) { + this@ObjectFieldLookup.reader.getAllBy(ids, "retrievableId").filter { it.retrievableId != null }.associateBy { it.retrievableId!! } + } else { + emptyMap() + } + + /* Emit retrievable with added attribute. */ + enrich.forEach { + val descriptor = descriptors[it.id] + if (descriptor != null) { + it.addAttribute(DescriptorAttribute(descriptor)) + } + } + + /* Emit input. */ + inputRetrieved.forEach { emit(it) } + } +} \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/ObjectFieldLookupFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/ObjectFieldLookupFactory.kt new file mode 100644 index 00000000..119c6a4c --- /dev/null +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/transform/lookup/ObjectFieldLookupFactory.kt @@ -0,0 +1,22 @@ +package org.vitrivr.engine.query.transform.lookup + +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.retrievable.Retrieved +import org.vitrivr.engine.core.operators.Operator +import org.vitrivr.engine.core.operators.retrieve.TransformerFactory + + +/** + * [TransformerFactory] for [ObjectFieldLookup]. + * + * @version 1.0.0 + * @author Ralph Gasser + */ +class ObjectFieldLookupFactory() : TransformerFactory { + override fun newTransformer(input: Operator, schema: Schema, properties: Map): ObjectFieldLookup { + val field = properties["field"] ?: throw IllegalArgumentException("Expected 'field' to be defined in properties") + val predicates = properties["predicates"]?.split(",")?.toSet() ?: emptySet() + val reader = (schema[field] ?: throw IllegalArgumentException("Field '$field' not defined in schema")).getReader() + return ObjectFieldLookup(input, reader, predicates) + } +} \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.retrieve.TransformerFactory b/vitrivr-engine-query/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.retrieve.TransformerFactory index b4821e9b..1e4d0593 100644 --- a/vitrivr-engine-query/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.retrieve.TransformerFactory +++ b/vitrivr-engine-query/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.retrieve.TransformerFactory @@ -1,3 +1,4 @@ org.vitrivr.engine.query.transform.RelationExpanderFactory org.vitrivr.engine.query.transform.ScoreAggregatorFactory -org.vitrivr.engine.query.transform.FieldLookupFactory \ No newline at end of file +org.vitrivr.engine.query.transform.lookup.FieldLookupFactory +org.vitrivr.engine.query.transform.lookup.ObjectFieldLookupFactory \ No newline at end of file