All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dizitart.no2.collection.operation.ReadOperations Maven / Gradle / Ivy

/*
 * Copyright (c) 2017-2020. Nitrite author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dizitart.no2.collection.operation;

import org.dizitart.no2.NitriteConfig;
import org.dizitart.no2.collection.*;
import org.dizitart.no2.common.RecordStream;
import org.dizitart.no2.common.streams.*;
import org.dizitart.no2.common.tuples.Pair;
import org.dizitart.no2.filters.*;
import org.dizitart.no2.index.IndexDescriptor;
import org.dizitart.no2.index.NitriteIndexer;
import org.dizitart.no2.common.processors.ProcessorChain;
import org.dizitart.no2.store.NitriteMap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

import static org.dizitart.no2.common.tuples.Pair.pair;

/**
 * @author Anindya Chatterjee
 * @since 1.0
 */
class ReadOperations {
    private final String collectionName;
    private final NitriteConfig nitriteConfig;
    private final NitriteMap nitriteMap;
    private final FindOptimizer findOptimizer;
    private final IndexOperations indexOperations;
    private final ProcessorChain processorChain;

    ReadOperations(String collectionName,
                   IndexOperations indexOperations,
                   NitriteConfig nitriteConfig,
                   NitriteMap nitriteMap,
                   ProcessorChain processorChain) {
        this.nitriteMap = nitriteMap;
        this.nitriteConfig = nitriteConfig;
        this.collectionName = collectionName;
        this.indexOperations = indexOperations;
        this.findOptimizer = new FindOptimizer();
        this.processorChain = processorChain;
    }

    public DocumentCursor find(Filter filter, FindOptions findOptions) {
        if (filter == null) {
            filter = Filter.ALL;
        }

        prepareFilter(filter);
        Collection indexDescriptors = indexOperations.listIndexes();
        FindPlan findPlan = findOptimizer.optimize(filter, findOptions, indexDescriptors);
        return createCursor(findPlan);
    }

    Document getById(NitriteId nitriteId) {
        Document document = nitriteMap.get(nitriteId);
        if (processorChain != null) {
            document = processorChain.processAfterRead(document);
        }
        return document;
    }

    private void prepareFilter(Filter filter) {
        if (filter instanceof NitriteFilter) {
            NitriteFilter nitriteFilter = (NitriteFilter) filter;
            prepareNitriteFilter(nitriteFilter);

            if (filter instanceof LogicalFilter) {
                LogicalFilter logicalFilter = (LogicalFilter) filter;
                prepareLogicalFilter(logicalFilter);
            }
        }
    }

    private void prepareNitriteFilter(NitriteFilter nitriteFilter) {
        nitriteFilter.setNitriteConfig(nitriteConfig);
        nitriteFilter.setCollectionName(collectionName);
    }

    private void prepareLogicalFilter(LogicalFilter logicalFilter) {
        List filters = logicalFilter.getFilters();
        for (Filter filter : filters) {
            if (filter instanceof NitriteFilter) {
                NitriteFilter nitriteFilter = (NitriteFilter) filter;
                nitriteFilter.setObjectFilter(logicalFilter.getObjectFilter());
            }
            prepareFilter(filter);
        }
    }

    private DocumentCursor createCursor(FindPlan findPlan) {
        RecordStream> recordStream = findSuitableStream(findPlan);
        DocumentStream cursor = new DocumentStream(recordStream, processorChain);
        cursor.setFindPlan(findPlan);
        return cursor;
    }

    private RecordStream> findSuitableStream(FindPlan findPlan) {
        RecordStream> rawStream;

        if (!findPlan.getSubPlans().isEmpty()) {
            // or filters get all sub stream by finding suitable stream of all sub plans
            List>> subStreams = new ArrayList<>();
            for (FindPlan subPlan : findPlan.getSubPlans()) {
                RecordStream> suitableStream = findSuitableStream(subPlan);
                subStreams.add(suitableStream);
            }

            // concat all suitable stream of all sub plans
            rawStream = new ConcatStream(subStreams);

            if (findPlan.isDistinct()) {
                // return only distinct items
                rawStream = new DistinctStream(rawStream);
            }
        } else {
            // and or single filter
            if (findPlan.getByIdFilter() != null) {
                FieldBasedFilter byIdFilter = findPlan.getByIdFilter();
                NitriteId nitriteId = NitriteId.createId((String) byIdFilter.getValue());
                if (nitriteMap.containsKey(nitriteId)) {
                    Document document = nitriteMap.get(nitriteId);
                    rawStream = RecordStream.single(pair(nitriteId, document));
                } else {
                    rawStream = RecordStream.empty();
                }
            } else {
                IndexDescriptor indexDescriptor = findPlan.getIndexDescriptor();
                if (indexDescriptor != null) {
                    // get optimized filter
                    NitriteIndexer indexer = nitriteConfig.findIndexer(indexDescriptor.getIndexType());
                    LinkedHashSet nitriteIds = indexer.findByFilter(findPlan, nitriteConfig);

                    // create indexed stream from optimized filter
                    rawStream = new IndexedStream(nitriteIds, nitriteMap);
                } else {
                    rawStream = nitriteMap.entries();
                }
            }

            if (findPlan.getCollectionScanFilter() != null) {
                rawStream = new FilteredStream(rawStream, findPlan.getCollectionScanFilter());
            }
        }

        // sort and bound stage
        if (rawStream != null) {
            if (findPlan.getBlockingSortOrder() != null && !findPlan.getBlockingSortOrder().isEmpty()) {
                rawStream = new SortedDocumentStream(findPlan, rawStream);
            }

            if (findPlan.getLimit() != null || findPlan.getSkip() != null) {
                long limit = findPlan.getLimit() == null ? Long.MAX_VALUE : findPlan.getLimit();
                long skip = findPlan.getSkip() == null ? 0 : findPlan.getSkip();
                rawStream = new BoundedStream<>(skip, limit, rawStream);
            }
        }

        return rawStream;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy