use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class KeyExpressionTest method testConcatenateSingleRepeatedField.
@Test
public void testConcatenateSingleRepeatedField() throws Exception {
final KeyExpression expression = field("repeat_me", FanType.Concatenate);
expression.validate(TestScalarFieldAccess.getDescriptor());
assertFalse(expression.createsDuplicates());
assertEquals(Collections.singletonList(scalar(Arrays.asList("Boxes", "Bowls"))), evaluate(expression, plantsBoxesAndBowls));
assertEquals(Collections.singletonList(scalar(Collections.emptyList())), evaluate(expression, emptyScalar));
assertEquals(Collections.singletonList(scalar(Collections.emptyList())), evaluate(expression, null));
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class KeyExpressionTest method testFannedThenScalar.
@Test
public void testFannedThenScalar() throws Exception {
final KeyExpression expression = concat(field("repeat_me", FanType.FanOut), field("field"));
expression.validate(TestScalarFieldAccess.getDescriptor());
assertTrue(expression.createsDuplicates());
assertEquals(Arrays.asList(concatenate("Boxes", "Plants"), concatenate("Bowls", "Plants")), evaluate(expression, plantsBoxesAndBowls));
assertEquals(Collections.emptyList(), evaluate(expression, emptyScalar));
assertEquals(Collections.emptyList(), evaluate(expression, null));
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class KeyExpressionTest method testNestWithParentField.
@Test
public void testNestWithParentField() throws Exception {
final KeyExpression expression = concat(field("regular_old_field"), field("repeated_nesty", FanType.FanOut).nest("regular_old_field"));
expression.validate(NestedField.getDescriptor());
assertTrue(expression.createsDuplicates());
assertEquals(Arrays.asList(concatenate("Grandmother", "Daughter"), concatenate("Grandmother", "Sister")), evaluate(expression, matryoshkaDolls));
assertEquals(Collections.emptyList(), evaluate(expression, emptyNested));
assertEquals(Arrays.asList(Key.Evaluated.concatenate("Lonely", NULL), Key.Evaluated.concatenate("Lonely", NULL)), evaluate(expression, lonelyDoll));
assertEquals(Collections.emptyList(), evaluate(expression, null));
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class UnionVisitor method postVisit.
@Nonnull
@Override
public RecordQueryPlan postVisit(@Nonnull final RecordQueryPlan recordQueryPlan) {
if (recordQueryPlan instanceof RecordQueryUnionPlanBase) {
RecordQueryUnionPlanBase unionPlan = (RecordQueryUnionPlanBase) recordQueryPlan;
final Set<KeyExpression> requiredFields = unionPlan.getRequiredFields();
boolean shouldPullOutFilter = false;
QueryComponent filter = null;
if (unionPlan.getChildren().stream().allMatch(child -> child instanceof RecordQueryFilterPlan)) {
filter = ((RecordQueryFilterPlan) unionPlan.getChildren().get(0)).getConjunctedFilter();
// needed for lambda expression
final QueryComponent finalFilter = filter;
shouldPullOutFilter = unionPlan.getChildren().stream().allMatch(plan -> ((RecordQueryFilterPlan) plan).getConjunctedFilter().equals(finalFilter));
}
List<ExpressionRef<RecordQueryPlan>> newChildren = new ArrayList<>(unionPlan.getChildren().size());
for (RecordQueryPlan plan : unionPlan.getChildren()) {
if (shouldPullOutFilter) {
// Check if the plan under the filter can have its index fetch removed.
if (!(plan instanceof RecordQueryFilterPlan)) {
throw new RecordCoreException("serious logic error: thought this was a filter plan but it wasn't");
}
plan = ((RecordQueryFilterPlan) plan).getChild();
}
@Nullable RecordQueryPlan newPlan = removeIndexFetch(plan, requiredFields);
if (newPlan == null) {
// can't remove index fetch, so give up
return recordQueryPlan;
}
newChildren.add(GroupExpressionRef.of(newPlan));
}
RecordQueryPlan newUnionPlan = new RecordQueryFetchFromPartialRecordPlan(unionPlan.withChildrenReferences(newChildren), TranslateValueFunction.unableToTranslate());
if (shouldPullOutFilter) {
return new RecordQueryFilterPlan(newUnionPlan, filter);
} else {
return newUnionPlan;
}
}
return recordQueryPlan;
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class LuceneDocumentFromRecordTest method mapWithSubMessageWithAmbiguity.
/**
* When a schema leads an ambiguity of the parsed path given a concatenated Lucene field, the first path that satisfies the given field will be selected and the correct one could be ignored.
* In this test, because both the path {entry -> sub_entry -> value} and {entry -> sub_entry -> second_value} could match with the given Lucene field "entry_k1_second_value",
* and in the first path the key is "k1_second" and in the second one the key is "k1".
* There is no more information to tell which is the expected one so we just pick up the first one to build the partial record.
* TODO: Predicate the potential ambiguity when loading a schema and reject it
*/
@Test
void mapWithSubMessageWithAmbiguity() {
TestRecordsTextProto.NestedMapDocument message = TestRecordsTextProto.NestedMapDocument.newBuilder().setDocId(5).addEntry(TestRecordsTextProto.NestedMapDocument.Entry.newBuilder().setKey("k1").setSubEntry(TestRecordsTextProto.NestedMapDocument.SubEntry.newBuilder().setSecondValue("testValue").build()).build()).build();
KeyExpression index = field("entry", KeyExpression.FanType.FanOut).nest(function(LuceneFunctionNames.LUCENE_FIELD_NAME, concat(field("sub_entry").nest(concat(function(LuceneFunctionNames.LUCENE_TEXT, field("value")), function(LuceneFunctionNames.LUCENE_TEXT, field("second_value")))), field("key"))));
FDBRecord<Message> record = unstoredRecord(message);
assertEquals(ImmutableMap.of(Tuple.from(), ImmutableList.of(textField("entry_k1_second_value", "testValue"))), LuceneDocumentFromRecord.getRecordFields(index, record));
// Build the partial record message for suggestion
Descriptors.Descriptor recordDescriptor = message.getDescriptorForType();
TestRecordsTextProto.NestedMapDocument.Builder builder = TestRecordsTextProto.NestedMapDocument.newBuilder();
LuceneIndexKeyValueToPartialRecordUtils.buildPartialRecord(index, recordDescriptor, builder, "entry_k1_second_value", "suggestion");
TestRecordsTextProto.NestedMapDocument partialMsg = builder.build();
assertEquals(1, partialMsg.getEntryCount());
TestRecordsTextProto.NestedMapDocument.Entry entry = partialMsg.getEntry(0);
// The k1_second is supposed to be populated for the key field under entry
assertEquals("k1_second", entry.getKey());
// The suggestion is supposed to show up in value field within sub-entry, instead of second_value
TestRecordsTextProto.NestedMapDocument.SubEntry subEntry = entry.getSubEntry();
assertEquals("suggestion", subEntry.getValue());
assertFalse(subEntry.hasSecondValue());
}
Aggregations