Search in sources :

Example 1 with IndexKeyValueToPartialRecord

use of com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord in project fdb-record-layer by FoundationDB.

the class RecordQueryPlannerSubstitutionVisitor method removeIndexFetch.

@Nullable
public static RecordQueryPlan removeIndexFetch(@Nonnull RecordMetaData recordMetaData, @Nonnull PlannableIndexTypes indexTypes, @Nullable KeyExpression commonPrimaryKey, @Nonnull RecordQueryPlan plan, @Nonnull Set<KeyExpression> requiredFields) {
    if (plan instanceof RecordQueryPlanWithIndex) {
        RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) plan;
        Index index = recordMetaData.getIndex(indexPlan.getIndexName());
        final Collection<RecordType> recordTypes = recordMetaData.recordTypesForIndex(index);
        if (recordTypes.size() != 1) {
            return null;
        }
        final RecordType recordType = Iterables.getOnlyElement(recordTypes);
        AvailableFields fieldsFromIndex = AvailableFields.fromIndex(recordType, index, indexTypes, commonPrimaryKey);
        Set<KeyExpression> fields = new HashSet<>(requiredFields);
        if (commonPrimaryKey != null) {
            // Need the primary key, even if it wasn't one of the explicit result fields.
            fields.addAll(commonPrimaryKey.normalizeKeyForPositions());
        }
        if (fieldsFromIndex.containsAll(fields)) {
            final IndexKeyValueToPartialRecord keyValueToPartialRecord = fieldsFromIndex.buildIndexKeyValueToPartialRecord(recordType).build();
            if (keyValueToPartialRecord != null) {
                return new RecordQueryCoveringIndexPlan(indexPlan, recordType.getName(), fieldsFromIndex, keyValueToPartialRecord);
            }
        }
    } else if (plan instanceof RecordQueryFetchFromPartialRecordPlan) {
        RecordQueryFetchFromPartialRecordPlan fetchPlan = (RecordQueryFetchFromPartialRecordPlan) plan;
        if (fetchPlan.getChild().getAvailableFields().containsAll(requiredFields)) {
            return ((RecordQueryFetchFromPartialRecordPlan) plan).getChild();
        }
    }
    return null;
}
Also used : AvailableFields(com.apple.foundationdb.record.query.plan.AvailableFields) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) RecordType(com.apple.foundationdb.record.metadata.RecordType) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index) HashSet(java.util.HashSet) Nullable(javax.annotation.Nullable)

Example 2 with IndexKeyValueToPartialRecord

use of com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord in project fdb-record-layer by FoundationDB.

the class LuceneIndexTest method searchForSpellcheckForGroupedRecord.

@Test
void searchForSpellcheckForGroupedRecord() throws Exception {
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, metaDataBuilder -> {
            metaDataBuilder.removeIndex(TextIndexTestUtils.SIMPLE_DEFAULT_NAME);
            metaDataBuilder.addIndex(MAP_DOC, MAP_ON_VALUE_INDEX);
        });
        FDBStoredRecord<Message> fdbRecord = recordStore.saveRecord(createMultiEntryMapDoc(1623L, ENGINEER_JOKE, "sampleTextPhrase", WAYLON, "sampleTextSong", 2));
        List<IndexEntry> indexEntries = recordStore.scanIndex(MAP_ON_VALUE_INDEX, IndexScanType.BY_LUCENE_SPELLCHECK, TupleRange.allOf(Tuple.from("Visin", "sampleTextPhrase")), null, ScanProperties.FORWARD_SCAN).asList().get();
        assertEquals(1, indexEntries.size());
        IndexEntry indexEntry = indexEntries.get(0);
        assertEquals(0.8F, indexEntry.getValue().get(0));
        Descriptors.Descriptor recordDescriptor = TestRecordsTextProto.MapDocument.getDescriptor();
        IndexKeyValueToPartialRecord toPartialRecord = LuceneIndexQueryPlan.getToPartialRecord(MAP_ON_VALUE_INDEX, fdbRecord.getRecordType(), IndexScanType.BY_LUCENE_SPELLCHECK);
        Message message = toPartialRecord.toRecord(recordDescriptor, indexEntry);
        Descriptors.FieldDescriptor entryDescriptor = recordDescriptor.findFieldByName("entry");
        Message entry = (Message) message.getRepeatedField(entryDescriptor, 0);
        Descriptors.FieldDescriptor keyDescriptor = entryDescriptor.getMessageType().findFieldByName("key");
        Descriptors.FieldDescriptor valueDescriptor = entryDescriptor.getMessageType().findFieldByName("value");
        // TODO: This seems like the wrong field string to return. I'm not sure what to do here
        assertEquals("sampleTextPhrase", entry.getField(keyDescriptor));
        assertEquals("vision", entry.getField(valueDescriptor));
    // assertEquals(1, context.getTimer().getCounter(FDBStoreTimer.Counts.LUCENE_SCAN_MATCHED_AUTO_COMPLETE_SUGGESTIONS).getCount());
    // assertEntriesAndSegmentInfoStoredInCompoundFile(recordStore.indexSubspace(MAP_ON_VALUE_INDEX_WITH_AUTO_COMPLETE).subspace(Tuple.from("sampleTextPhrase")), context, "_0.cfs", true);
    }
}
Also used : Message(com.google.protobuf.Message) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) IndexEntry(com.apple.foundationdb.record.IndexEntry) Descriptors(com.google.protobuf.Descriptors) Test(org.junit.jupiter.api.Test)

Example 3 with IndexKeyValueToPartialRecord

use of com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord 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();
}
Also used : RecordCoreException(com.apple.foundationdb.record.RecordCoreException) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 4 with IndexKeyValueToPartialRecord

use of com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord in project fdb-record-layer by FoundationDB.

the class LuceneIndexTest method searchForAutoCompleteForGroupedRecord.

@Test
void searchForAutoCompleteForGroupedRecord() throws Exception {
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, metaDataBuilder -> {
            metaDataBuilder.removeIndex(TextIndexTestUtils.SIMPLE_DEFAULT_NAME);
            metaDataBuilder.addIndex(MAP_DOC, MAP_ON_VALUE_INDEX_WITH_AUTO_COMPLETE);
        });
        FDBStoredRecord<Message> fdbRecord = recordStore.saveRecord(createMultiEntryMapDoc(1623L, ENGINEER_JOKE, "sampleTextPhrase", WAYLON, "sampleTextSong", 2));
        List<IndexEntry> indexEntries = recordStore.scanIndex(MAP_ON_VALUE_INDEX_WITH_AUTO_COMPLETE, IndexScanType.BY_LUCENE_AUTO_COMPLETE, TupleRange.allOf(Tuple.from("Vision", "sampleTextPhrase")), null, ScanProperties.FORWARD_SCAN).asList().get();
        assertEquals(1, indexEntries.size());
        IndexEntry indexEntry = indexEntries.get(0);
        Descriptors.Descriptor recordDescriptor = TestRecordsTextProto.MapDocument.getDescriptor();
        IndexKeyValueToPartialRecord toPartialRecord = LuceneIndexQueryPlan.getToPartialRecord(MAP_ON_VALUE_INDEX_WITH_AUTO_COMPLETE, fdbRecord.getRecordType(), IndexScanType.BY_LUCENE_AUTO_COMPLETE);
        Message message = toPartialRecord.toRecord(recordDescriptor, indexEntry);
        Descriptors.FieldDescriptor entryDescriptor = recordDescriptor.findFieldByName("entry");
        Message entry = (Message) message.getRepeatedField(entryDescriptor, 0);
        Descriptors.FieldDescriptor keyDescriptor = entryDescriptor.getMessageType().findFieldByName("key");
        Descriptors.FieldDescriptor valueDescriptor = entryDescriptor.getMessageType().findFieldByName("value");
        assertEquals("sampleTextPhrase", entry.getField(keyDescriptor));
        assertEquals(ENGINEER_JOKE, entry.getField(valueDescriptor));
        assertEquals(1, context.getTimer().getCounter(FDBStoreTimer.Counts.LUCENE_SCAN_MATCHED_AUTO_COMPLETE_SUGGESTIONS).getCount());
        assertEntriesAndSegmentInfoStoredInCompoundFile(AutoCompleteSuggesterCommitCheckAsync.getSuggestionIndexSubspace(recordStore.indexSubspace(MAP_ON_VALUE_INDEX_WITH_AUTO_COMPLETE), Tuple.from("sampleTextPhrase")), context, "_0.cfs", true);
    }
}
Also used : Message(com.google.protobuf.Message) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) IndexEntry(com.apple.foundationdb.record.IndexEntry) Descriptors(com.google.protobuf.Descriptors) Test(org.junit.jupiter.api.Test)

Example 5 with IndexKeyValueToPartialRecord

use of com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord in project fdb-record-layer by FoundationDB.

the class QueryPlanUtils method getCoveringIndexEntryToPartialRecordFunction.

/**
 * The method to get a function from an {@link IndexEntry} to a {@link FDBQueriedRecord} representing a partial record.
 */
@SuppressWarnings("unchecked")
public static <M extends Message> Function<IndexEntry, FDBQueriedRecord<M>> getCoveringIndexEntryToPartialRecordFunction(@Nonnull final FDBRecordStoreBase<M> store, @Nonnull final String recordTypeName, @Nonnull final String indexName, @Nonnull final IndexKeyValueToPartialRecord toRecord, @Nonnull final IndexScanType scanType) {
    final RecordMetaData metaData = store.getRecordMetaData();
    final RecordType recordType = metaData.getRecordType(recordTypeName);
    final Index index = metaData.getIndex(indexName);
    final Descriptors.Descriptor recordDescriptor = recordType.getDescriptor();
    boolean hasPrimaryKey = scanType != IndexScanType.BY_GROUP && scanType != IndexScanType.BY_LUCENE_AUTO_COMPLETE && scanType != IndexScanType.BY_LUCENE_SPELLCHECK;
    return indexEntry -> store.coveredIndexQueriedRecord(index, indexEntry, recordType, (M) toRecord.toRecord(recordDescriptor, indexEntry), hasPrimaryKey);
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) IndexScanType(com.apple.foundationdb.record.IndexScanType) RecordType(com.apple.foundationdb.record.metadata.RecordType) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) Index(com.apple.foundationdb.record.metadata.Index) Descriptors(com.google.protobuf.Descriptors) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Message(com.google.protobuf.Message) Nonnull(javax.annotation.Nonnull) Function(java.util.function.Function) FDBRecordStoreBase(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) Descriptors(com.google.protobuf.Descriptors)

Aggregations

IndexKeyValueToPartialRecord (com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord)5 IndexEntry (com.apple.foundationdb.record.IndexEntry)3 Descriptors (com.google.protobuf.Descriptors)3 Message (com.google.protobuf.Message)3 Index (com.apple.foundationdb.record.metadata.Index)2 RecordType (com.apple.foundationdb.record.metadata.RecordType)2 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)2 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)2 Test (org.junit.jupiter.api.Test)2 IndexScanType (com.apple.foundationdb.record.IndexScanType)1 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)1 RecordMetaData (com.apple.foundationdb.record.RecordMetaData)1 GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)1 FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)1 FDBRecordStoreBase (com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase)1 AvailableFields (com.apple.foundationdb.record.query.plan.AvailableFields)1 RecordQueryCoveringIndexPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan)1 RecordQueryFetchFromPartialRecordPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan)1 RecordQueryPlanWithIndex (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex)1 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1