org.springframework.data.mongodb.core.mapreduce.MapReduceOptions.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.data.mongodb.core.mapreduce.MapReduceOptions.java

Source

/*
 * Copyright 2010-2019 the original 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
 *
 *      https://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.springframework.data.mongodb.core.mapreduce;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.bson.Document;
import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.lang.Nullable;

import com.mongodb.MapReduceCommand;
import com.mongodb.MapReduceCommand.OutputType;
import com.mongodb.client.model.MapReduceAction;

/**
 * @author Mark Pollack
 * @author Oliver Gierke
 * @author Christoph Strobl
 * @author Mark Paluch
 */
public class MapReduceOptions {

    private @Nullable String outputCollection;

    private Optional<String> outputDatabase = Optional.empty();
    private MapReduceCommand.OutputType outputType = MapReduceCommand.OutputType.REPLACE;
    private Map<String, Object> scopeVariables = new HashMap<>();
    private Map<String, Object> extraOptions = new HashMap<>();
    private @Nullable Boolean jsMode;
    private Boolean verbose = Boolean.TRUE;
    private @Nullable Integer limit;

    private Optional<Boolean> outputSharded = Optional.empty();
    private Optional<String> finalizeFunction = Optional.empty();
    private Optional<Collation> collation = Optional.empty();

    /**
     * Static factory method to create a MapReduceOptions instance
     *
     * @return a new instance
     */
    public static MapReduceOptions options() {
        return new MapReduceOptions();
    }

    /**
     * Limit the number of objects to return from the collection that is fed into the map reduce operation Often used in
     * conjunction with a query and sort option so as to reduce the portion of the data that will be processed.
     *
     * @param limit Limit the number of objects to process
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions limit(int limit) {

        this.limit = limit;
        return this;
    }

    /**
     * The collection where the results from the map-reduce operation will be stored. Note, you can set the database name
     * as well with the outputDatabase option.
     *
     * @param collectionName The name of the collection where the results of the map-reduce operation will be stored.
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions outputCollection(String collectionName) {

        this.outputCollection = collectionName;
        return this;
    }

    /**
     * The database where the results from the map-reduce operation will be stored. Note, you ca set the collection name
     * as well with the outputCollection option.
     *
     * @param outputDatabase The name of the database where the results of the map-reduce operation will be stored.
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions outputDatabase(@Nullable String outputDatabase) {

        this.outputDatabase = Optional.ofNullable(outputDatabase);
        return this;
    }

    /**
     * With this option, no collection will be created, and the whole map-reduce operation will happen in RAM. Also, the
     * results of the map-reduce will be returned within the result object. Note that this option is possible only when
     * the result set fits within the 16MB limit of a single document.
     *
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions outputTypeInline() {

        this.outputType = MapReduceCommand.OutputType.INLINE;
        return this;
    }

    /**
     * This option will merge new data into the old output collection. In other words, if the same key exists in both the
     * result set and the old collection, the new key will overwrite the old one.
     *
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions outputTypeMerge() {

        this.outputType = MapReduceCommand.OutputType.MERGE;
        return this;
    }

    /**
     * If documents exists for a given key in the result set and in the old collection, then a reduce operation (using the
     * specified reduce function) will be performed on the two values and the result will be written to the output
     * collection. If a finalize function was provided, this will be run after the reduce as well.
     *
     * @return
     */
    public MapReduceOptions outputTypeReduce() {
        this.outputType = MapReduceCommand.OutputType.REDUCE;
        return this;
    }

    /**
     * The output will be inserted into a collection which will atomically replace any existing collection with the same
     * name. Note, the default is MapReduceCommand.OutputType.REPLACE
     *
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions outputTypeReplace() {

        this.outputType = MapReduceCommand.OutputType.REPLACE;
        return this;
    }

    /**
     * If true and combined with an output mode that writes to a collection, the output collection will be sharded using
     * the _id field. For MongoDB 1.9+
     *
     * @param outputShared if true, output will be sharded based on _id key.
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions outputSharded(boolean outputShared) {

        this.outputSharded = Optional.of(outputShared);
        return this;
    }

    /**
     * Sets the finalize function
     *
     * @param finalizeFunction The finalize function. Can be a JSON string or a Spring Resource URL
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions finalizeFunction(@Nullable String finalizeFunction) {

        this.finalizeFunction = Optional.ofNullable(finalizeFunction);
        return this;
    }

    /**
     * Key-value pairs that are placed into JavaScript global scope and can be accessed from map, reduce, and finalize
     * scripts.
     *
     * @param scopeVariables variables that can be accessed from map, reduce, and finalize scripts
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions scopeVariables(Map<String, Object> scopeVariables) {

        this.scopeVariables = scopeVariables;
        return this;
    }

    /**
     * Flag that toggles behavior in the map-reduce operation so as to avoid intermediate conversion to BSON between the
     * map and reduce steps. For MongoDB 1.9+
     *
     * @param javaScriptMode if true, have the execution of map-reduce stay in JavaScript
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions javaScriptMode(boolean javaScriptMode) {

        this.jsMode = javaScriptMode;
        return this;
    }

    /**
     * Flag to set that will provide statistics on job execution time.
     *
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     */
    public MapReduceOptions verbose(boolean verbose) {

        this.verbose = verbose;
        return this;
    }

    /**
     * Add additional extra options that may not have a method on this class. This method will help if you use a version
     * of this client library with a server version that has added additional map-reduce options that do not yet have an
     * method for use in setting them. options
     *
     * @param key The key option
     * @param value The value of the option
     * @return MapReduceOptions so that methods can be chained in a fluent API style
     * @deprecated since 1.7.
     */
    @Deprecated
    public MapReduceOptions extraOption(String key, Object value) {

        extraOptions.put(key, value);
        return this;
    }

    /**
     * Define the Collation specifying language-specific rules for string comparison.
     *
     * @param collation can be {@literal null}.
     * @return
     * @since 2.0
     */
    public MapReduceOptions collation(@Nullable Collation collation) {

        this.collation = Optional.ofNullable(collation);
        return this;
    }

    /**
     * @return
     * @deprecated since 1.7
     */
    @Deprecated
    public Map<String, Object> getExtraOptions() {
        return extraOptions;
    }

    public Optional<String> getFinalizeFunction() {
        return this.finalizeFunction;
    }

    @Nullable
    public Boolean getJavaScriptMode() {
        return this.jsMode;
    }

    @Nullable
    public String getOutputCollection() {
        return this.outputCollection;
    }

    public Optional<String> getOutputDatabase() {
        return this.outputDatabase;
    }

    public Optional<Boolean> getOutputSharded() {
        return this.outputSharded;
    }

    public MapReduceCommand.OutputType getOutputType() {
        return this.outputType;
    }

    public Map<String, Object> getScopeVariables() {
        return this.scopeVariables;
    }

    /**
     * Get the maximum number of documents for the input into the map function.
     *
     * @return {@literal null} if not set.
     */
    @Nullable
    public Integer getLimit() {
        return limit;
    }

    /**
     * Get the Collation specifying language-specific rules for string comparison.
     *
     * @return
     * @since 2.0
     */
    public Optional<Collation> getCollation() {
        return collation;
    }

    /**
     * Return the {@link MapReduceAction} derived from {@link com.mongodb.MapReduceCommand.OutputType}.
     *
     * @return the mapped action or {@literal null} if the action maps to inline output.
     * @since 2.0.10
     */
    @Nullable
    public MapReduceAction getMapReduceAction() {

        switch (outputType) {
        case MERGE:
            return MapReduceAction.MERGE;
        case REDUCE:
            return MapReduceAction.REDUCE;
        case REPLACE:
            return MapReduceAction.REPLACE;
        case INLINE:
            return null;
        default:
            throw new IllegalStateException(
                    String.format("Unknown output type %s for map reduce command.", outputType));
        }
    }

    /**
     * @return {@literal true} if {@link OutputType#INLINE} is used.
     * @since 2.0.10
     */
    public boolean usesInlineOutput() {
        return OutputType.INLINE.equals(outputType);
    }

    public Document getOptionsObject() {

        Document cmd = new Document();

        if (verbose != null) {
            cmd.put("verbose", verbose);
        }

        cmd.put("out", createOutObject());

        finalizeFunction.ifPresent(val -> cmd.append("finalize", val));

        if (scopeVariables != null) {
            cmd.put("scope", scopeVariables);
        }

        if (limit != null) {
            cmd.put("limit", limit);
        }

        if (!extraOptions.keySet().isEmpty()) {
            cmd.putAll(extraOptions);
        }

        getCollation().ifPresent(val -> cmd.append("collation", val.toDocument()));

        return cmd;
    }

    protected Document createOutObject() {

        Document out = new Document();

        switch (getOutputType()) {
        case INLINE:
            out.put("inline", 1);
            break;
        case REPLACE:
            out.put("replace", outputCollection);
            break;
        case MERGE:
            out.put("merge", outputCollection);
            break;
        case REDUCE:
            out.put("reduce", outputCollection);
            break;
        }

        outputDatabase.ifPresent(val -> out.append("db", val));
        outputSharded.ifPresent(val -> out.append("sharded", val));

        return out;
    }
}