use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class LuceneIndexQueryPlan method getToPartialRecord.
/**
* Get the {@link IndexKeyValueToPartialRecord} instance for an {@link IndexEntry} representing a result of Lucene auto-complete suggestion.
* The partial record contains the suggestion in the field where it is indexed from, and the grouping keys if there are any.
*/
@VisibleForTesting
public static IndexKeyValueToPartialRecord getToPartialRecord(@Nonnull Index index, @Nonnull RecordType recordType, @Nonnull IndexScanType scanType) {
final IndexKeyValueToPartialRecord.Builder builder = IndexKeyValueToPartialRecord.newBuilder(recordType);
KeyExpression root = index.getRootExpression();
if (root instanceof GroupingKeyExpression) {
KeyExpression groupingKey = ((GroupingKeyExpression) root).getGroupingSubKey();
for (int i = 0; i < groupingKey.getColumnSize(); i++) {
AvailableFields.addCoveringField(groupingKey, AvailableFields.FieldData.of(IndexKeyValueToPartialRecord.TupleSource.KEY, i), builder);
}
}
builder.addRequiredMessageFields();
if (!builder.isValid(true)) {
throw new RecordCoreException("Missing required field for result record").addLogInfo(LogMessageKeys.INDEX_NAME, index.getName()).addLogInfo(LogMessageKeys.RECORD_TYPE, recordType.getName()).addLogInfo(LogMessageKeys.SCAN_TYPE, scanType);
}
builder.addRegularCopier(new LuceneIndexKeyValueToPartialRecordUtils.LuceneAutoCompleteCopier());
return builder.build();
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class LucenePlanner method planLucene.
@Override
protected ScoredPlan planLucene(@Nonnull CandidateScan candidateScan, @Nonnull Index index, @Nonnull QueryComponent filter, @Nullable KeyExpression sort) {
FilterSatisfiedMask filterMask = FilterSatisfiedMask.of(filter);
KeyExpression rootExp = index.getRootExpression();
ScanComparisons groupingComparisons;
// Getting grouping information from the index key and query filter
if (rootExp instanceof GroupingKeyExpression) {
KeyExpression groupingKey = ((GroupingKeyExpression) rootExp).getGroupingSubKey();
QueryToKeyMatcher.Match groupingMatch = new QueryToKeyMatcher(filter).matchesCoveringKey(groupingKey, filterMask);
if (!groupingMatch.getType().equals((QueryToKeyMatcher.MatchType.EQUALITY))) {
return null;
}
groupingComparisons = new ScanComparisons(groupingMatch.getEqualityComparisons(), Collections.emptySet());
} else {
groupingComparisons = null;
}
LuceneIndexQueryPlan lucenePlan = getComparisonsForLuceneFilter(index, null, filter, filterMask, groupingComparisons);
if (lucenePlan == null) {
return null;
}
RecordQueryPlan plan = lucenePlan;
plan = addTypeFilterIfNeeded(candidateScan, plan, getPossibleTypes(index));
if (filterMask.allSatisfied()) {
filterMask.setSatisfied(true);
}
return new ScoredPlan(plan, filterMask.getUnsatisfiedFilters(), Collections.emptyList(), 11 - filterMask.getUnsatisfiedFilters().size(), lucenePlan.createsDuplicates(), null);
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class LuceneIndexKeyValueToPartialRecordUtils method buildPartialRecord.
public static void buildPartialRecord(@Nonnull KeyExpression root, @Nonnull Descriptors.Descriptor descriptor, @Nonnull Message.Builder builder, @Nonnull String luceneField, @Nonnull String suggestion, @Nonnull Tuple groupingKey) {
final KeyExpression expression = root instanceof GroupingKeyExpression ? ((GroupingKeyExpression) root).getWholeKey() : root;
LuceneIndexExpressions.getFieldsRecursively(expression, new PartialRecordBuildSource(null, descriptor, builder), (source, fieldName, value, type, stored, overriddenKeyRanges, groupingKeyIndex) -> {
if (groupingKeyIndex > -1) {
if (groupingKeyIndex > groupingKey.size() - 1) {
throw new RecordCoreException("Invalid grouping value tuple given a grouping key").addLogInfo(LogMessageKeys.VALUE, groupingKey.toString());
}
source.buildMessage(groupingKey.get(groupingKeyIndex), (String) value, null, null, false);
} else if (type.equals(LuceneIndexExpressions.DocumentFieldType.TEXT)) {
buildIfFieldNameMatch(source, fieldName, luceneField, overriddenKeyRanges, suggestion, (String) value);
}
}, null, 0, root instanceof GroupingKeyExpression ? ((GroupingKeyExpression) root).getGroupingCount() : 0, new ArrayList<>());
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreDeleteWhereTest method openRecordWithHeaderPrimaryKey.
@SuppressWarnings("deprecation")
private KeyExpression openRecordWithHeaderPrimaryKey(FDBRecordContext context, boolean useCountIndex) throws Exception {
final KeyExpression groupExpr = field("header").nest("rec_no");
openRecordWithHeader(context, metaData -> {
metaData.getRecordType("MyRecord").setPrimaryKey(field("header").nest(concatenateFields("rec_no", "path")));
metaData.addIndex("MyRecord", "MyRecord$str_value", concat(groupExpr, field("str_value")));
if (useCountIndex) {
metaData.addUniversalIndex(new Index("MyRecord$count", new GroupingKeyExpression(groupExpr, 0), IndexTypes.COUNT));
} else {
metaData.setRecordCountKey(groupExpr);
}
});
return groupExpr;
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method minMaxTupleGrouped.
@Test
public void minMaxTupleGrouped() throws Exception {
final ThenKeyExpression tupleKey = concat(field("str_value_indexed"), field("num_value_2"));
final GroupingKeyExpression byKey = tupleKey.groupBy(field("num_value_3_indexed"));
final RecordMetaDataHook hook = md -> {
RecordTypeBuilder type = md.getRecordType("MySimpleRecord");
md.addIndex(type, new Index("min", byKey, IndexTypes.MIN_EVER_TUPLE));
md.addIndex(type, new Index("max", byKey, IndexTypes.MAX_EVER_TUPLE));
};
final IndexAggregateFunction minOverall = new IndexAggregateFunction(FunctionNames.MIN_EVER, tupleKey, null);
final IndexAggregateFunction maxOverall = new IndexAggregateFunction(FunctionNames.MAX_EVER, tupleKey, null);
final IndexAggregateFunction minByKey = new IndexAggregateFunction(FunctionNames.MIN_EVER, byKey, null);
final IndexAggregateFunction maxByKey = new IndexAggregateFunction(FunctionNames.MAX_EVER, byKey, null);
List<String> types = Collections.singletonList("MySimpleRecord");
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertNull(recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, minByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, maxByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
for (int i = 0; i < 100; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(i);
recBuilder.setNumValue3Indexed(i % 3);
recBuilder.setStrValueIndexed((i & 1) == 1 ? "odd" : "even");
recBuilder.setNumValue2(i / 2);
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertEquals(Tuple.from("even", 0), recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from("odd", 49), recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from("even", 2), recordStore.evaluateAggregateFunction(types, minByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from("odd", 48), recordStore.evaluateAggregateFunction(types, maxByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
commit(context);
}
}
Aggregations