Skip to content

Commit

Permalink
Add Aggregates.fill
Browse files Browse the repository at this point in the history
  • Loading branch information
stIncMale committed Jun 28, 2022
1 parent 805d770 commit a78faf2
Show file tree
Hide file tree
Showing 20 changed files with 1,018 additions and 8 deletions.
61 changes: 60 additions & 1 deletion driver-core/src/main/com/mongodb/client/model/Aggregates.java
Expand Up @@ -17,6 +17,8 @@
package com.mongodb.client.model;

import com.mongodb.MongoNamespace;
import com.mongodb.client.model.fill.FillComputation;
import com.mongodb.client.model.fill.FillOptions;
import com.mongodb.client.model.search.SearchOperator;
import com.mongodb.client.model.search.SearchCollector;
import com.mongodb.client.model.search.SearchOptions;
Expand All @@ -26,6 +28,7 @@
import org.bson.BsonDocumentWriter;
import org.bson.BsonInt32;
import org.bson.BsonString;
import org.bson.BsonType;
import org.bson.BsonValue;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;
Expand All @@ -35,9 +38,11 @@
import java.util.Objects;

import static com.mongodb.assertions.Assertions.assertTrue;
import static com.mongodb.assertions.Assertions.isTrueArgument;
import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.internal.Iterables.concat;
import static com.mongodb.internal.client.model.Util.sizeAtLeast;
import static java.util.Arrays.asList;
import static org.bson.assertions.Assertions.notNull;

/**
* Builders for aggregation pipeline stages.
Expand Down Expand Up @@ -655,6 +660,60 @@ public static <TExpression> Bson setWindowFields(@Nullable final TExpression par
return new SetWindowFieldsStage<>(partitionBy, sortBy, output);
}

/**
* Creates a {@code $fill} pipeline stage, which sets values to fields when they are {@link BsonType#NULL Null} or missing.
*
* @param options The fill options.
* @param output The {@link FillComputation}.
* @param moreOutput More {@link FillComputation}s.
* @return The requested pipeline stage.
* @mongodb.driver.dochub reference/operator/aggregation/fill/ $fill
* @mongodb.server.release 5.3
* @since 4.7
*/
public static Bson fill(final FillOptions options, final FillComputation output, final FillComputation... moreOutput) {
return fill(options, concat(notNull("output", output), moreOutput));
}

/**
* Creates a {@code $fill} pipeline stage, which sets values to fields when they are {@link BsonType#NULL Null} or missing.
*
* @param options The fill options.
* @param output The non-empty {@link FillComputation}s.
* @return The requested pipeline stage.
* @mongodb.driver.dochub reference/operator/aggregation/fill/ $fill
* @mongodb.server.release 5.3
* @since 4.7
*/
public static Bson fill(final FillOptions options, final Iterable<? extends FillComputation> output) {
notNull("options", options);
notNull("output", output);
isTrueArgument("output must not be empty", sizeAtLeast(output, 1));
return new Bson() {
@Override
public <TDocument> BsonDocument toBsonDocument(final Class<TDocument> documentClass, final CodecRegistry codecRegistry) {
BsonDocument fillSpecificationDoc = new BsonDocument();
fillSpecificationDoc.putAll(options.toBsonDocument(documentClass, codecRegistry));
BsonDocument outputDoc = new BsonDocument();
for (final FillComputation computation : output) {
BsonDocument computationDoc = computation.toBsonDocument(documentClass, codecRegistry);
assertTrue(computationDoc.size() == 1);
outputDoc.putAll(computationDoc);
}
fillSpecificationDoc.append("output", outputDoc);
return new BsonDocument("$fill", fillSpecificationDoc);
}

@Override
public String toString() {
return "Stage{name='$fill'"
+ ", options=" + options
+ ", output=" + output
+ '}';
}
};
}

/**
* Creates a {@code $search} pipeline stage supported by MongoDB Atlas.
* You may use the {@code $meta: "searchScore"} expression, e.g., via {@link Projections#metaSearchScore(String)},
Expand Down
Expand Up @@ -785,7 +785,7 @@ public static WindowedComputation denseRank(final String path) {
}

/**
* Builds a computation of the last observed non-{@code null} evaluation result of the {@code expression}.
* Builds a computation of the last observed non-{@link BsonType#NULL Null} evaluation result of the {@code expression}.
*
* @param path The output field path.
* @param expression The expression.
Expand All @@ -802,10 +802,10 @@ public static <TExpression> WindowedComputation locf(final String path, final TE
}

/**
* Builds a computation of a value that is equal to the evaluation result of the {@code expression} when it is non-{@code null},
* or to the linear interpolation of surrounding evaluation results of the {@code expression} when the result is {@code null}.
* Builds a computation of a value that is equal to the evaluation result of the {@code expression} when it is non-{@link BsonType#NULL Null},
* or to the linear interpolation of surrounding evaluation results of the {@code expression} when the result is {@link BsonType#NULL Null}.
* <p>
* {@linkplain Aggregates#setWindowFields(Object, Bson, List) Sorting} is required.</p>
* {@linkplain Aggregates#setWindowFields(Object, Bson, Iterable) Sorting} is required.</p>
*
* @param path The output field path.
* @param expression The expression.
Expand Down
@@ -0,0 +1,96 @@
/*
* Copyright 2008-present MongoDB, Inc.
*
* 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 com.mongodb.client.model.fill;

import com.mongodb.annotations.Evolving;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.WindowedComputations;
import org.bson.Document;
import org.bson.conversions.Bson;

import static com.mongodb.assertions.Assertions.notNull;

/**
* The core part of the {@code $fill} pipeline stage of an aggregation pipeline.
* A pair of an expression/method and a path to a field to be filled with evaluation results of the expression/method.
*
* @see Aggregates#fill(FillOptions, Iterable)
* @see Aggregates#fill(FillOptions, FillComputation, FillComputation...)
* @mongodb.server.release 5.3
* @since 4.7
*/
@Evolving
public interface FillComputation extends Bson {
/**
* Returns a {@link FillComputation} that uses the specified {@code expression}.
*
* @param field The field to fill.
* @param expression The expression.
* @param <TExpression> The {@code expression} type.
* @return The requested {@link FillComputation}.
* @mongodb.driver.manual core/document/#dot-notation Dot notation
*/
static <TExpression> ValueFillComputation value(final String field, TExpression expression) {
return new FillConstructibleBsonElement(notNull("field", field),
new Document("value", (notNull("expression", expression))));
}

/**
* Returns a {@link FillComputation} that uses the {@link WindowedComputations#locf(String, Object) locf} method.
*
* @param field The field to fill.
* @return The requested {@link FillComputation}.
* @mongodb.driver.manual core/document/#dot-notation Dot notation
*/
static LocfFillComputation locf(final String field) {
return new FillConstructibleBsonElement(notNull("field", field),
new Document("method", "locf"));
}

/**
* Returns a {@link FillComputation} that uses the {@link WindowedComputations#linearFill(String, Object) linear} method.
* <p>
* {@linkplain FillOptions#sortBy(Bson) Sorting} is required.</p>
*
* @param field The field to fill.
* @return The requested {@link FillComputation}.
* @mongodb.driver.manual core/document/#dot-notation Dot notation
*/
static LinearFillComputation linear(final String field) {
return new FillConstructibleBsonElement(notNull("field", field),
new Document("method", "linear"));
}

/**
* Creates a {@link FillComputation} from a {@link Bson} in situations when there is no builder method
* that better satisfies your needs.
* This method cannot be used to validate the syntax.
* <p>
* <i>Example</i><br>
* The following code creates two functionally equivalent {@link FillComputation}s,
* though they may not be {@linkplain Object#equals(Object) equal}.
* <pre>{@code
* FillComputation field1 = FillComputation.locf("fieldName");
* FillComputation field2 = FillComputation.of(new Document("fieldName", new Document("method", "locf")));
* }</pre>
*
* @param fill A {@link Bson} representing the required {@link FillComputation}.
* @return The requested {@link FillComputation}.
*/
static FillComputation of(final Bson fill) {
return new FillConstructibleBsonElement(notNull("fill", fill));
}
}
@@ -0,0 +1,70 @@
/*
* Copyright 2008-present MongoDB, Inc.
*
* 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 com.mongodb.client.model.fill;

import com.mongodb.internal.client.model.AbstractConstructibleBson;
import org.bson.Document;
import org.bson.conversions.Bson;

import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.internal.client.model.Util.sizeAtLeast;

final class FillConstructibleBson extends AbstractConstructibleBson<FillConstructibleBson> implements FillOptions {
static final FillConstructibleBson EMPTY_IMMUTABLE = new FillConstructibleBson(AbstractConstructibleBson.EMPTY_IMMUTABLE);

FillConstructibleBson(final Bson base) {
super(base);
}

private FillConstructibleBson(final Bson base, final Document appended) {
super(base, appended);
}

@Override
protected FillConstructibleBson newSelf(final Bson base, final Document appended) {
return new FillConstructibleBson(base, appended);
}

@Override
public <TExpression> FillOptions partitionBy(final TExpression partitionBy) {
return newMutated(doc -> {
doc.remove("partitionByFields");
doc.append("partitionBy", notNull("partitionBy", partitionBy));
});
}

@Override
public FillOptions partitionByFields(final Iterable<String> partitionByFields) {
return newMutated(doc -> {
doc.remove("partitionBy");
if (sizeAtLeast(partitionByFields, 1)) {
doc.append("partitionByFields", notNull("partitionByFields", partitionByFields));
} else {
doc.remove("partitionByFields");
}
});
}

@Override
public FillOptions sortBy(final Bson sortBy) {
return newAppended("sortBy", notNull("sortBy", sortBy));
}

@Override
public FillOptions option(final String name, final Object value) {
return newAppended(notNull("name", name), notNull("value", value));
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2008-present MongoDB, Inc.
*
* 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 com.mongodb.client.model.fill;

import com.mongodb.internal.client.model.AbstractConstructibleBsonElement;
import org.bson.conversions.Bson;

final class FillConstructibleBsonElement extends AbstractConstructibleBsonElement<FillConstructibleBsonElement> implements
ValueFillComputation, LocfFillComputation, LinearFillComputation {
FillConstructibleBsonElement(final String name, final Bson value) {
super(name, value);
}

FillConstructibleBsonElement(final Bson baseElement) {
super(baseElement);
}

private FillConstructibleBsonElement(final Bson baseElement, final Bson appendedElementValue) {
super(baseElement, appendedElementValue);
}

@Override
protected FillConstructibleBsonElement newSelf(final Bson baseElement, final Bson appendedElementValue) {
return new FillConstructibleBsonElement(baseElement, appendedElementValue);
}
}

0 comments on commit a78faf2

Please sign in to comment.