com.mongodb.client.model.Updates Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongodb-driver-core Show documentation
Show all versions of mongodb-driver-core Show documentation
The Java operations layer for the MongoDB Java Driver. Third parties can ' +
'wrap this layer to provide custom higher-level APIs
/*
* 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;
import com.mongodb.lang.Nullable;
import org.bson.BsonDocument;
import org.bson.BsonDocumentWriter;
import org.bson.BsonInt32;
import org.bson.BsonInt64;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.client.model.BuildersHelper.encodeValue;
import static java.util.Arrays.asList;
/**
* A factory for document updates. A convenient way to use this class is to statically import all of its methods, which allows usage like:
*
* collection.updateOne(eq("x", 1), set("x", 2));
*
*
* @since 3.1
* @mongodb.driver.manual reference/operator/update/ Update Operators
*/
public final class Updates {
/**
* Combine a list of updates into a single update.
*
* @param updates the list of updates
* @return a combined update
*/
public static Bson combine(final Bson... updates) {
return combine(asList(updates));
}
/**
* Combine a list of updates into a single update.
*
* @param updates the list of updates
* @return a combined update
*/
public static Bson combine(final List extends Bson> updates) {
notNull("updates", updates);
return new CompositeUpdate(updates);
}
/**
* Creates an update that sets the value of the field with the given name to the given value.
*
* @param fieldName the non-null field name
* @param value the value, which may be null
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/set/ $set
*/
public static Bson set(final String fieldName, @Nullable final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$set");
}
/**
* Creates an update that deletes the field with the given name.
*
* @param fieldName the non-null field name
* @return the update
* @mongodb.driver.manual reference/operator/update/unset/ $unset
*/
public static Bson unset(final String fieldName) {
return new SimpleUpdate<>(fieldName, "", "$unset");
}
/**
* Creates an update that sets the values for the document, but only if the update is an upsert that results in an insert of a document.
*
* @param value the value
* @return the update
* @mongodb.driver.manual reference/operator/update/setOnInsert/ $setOnInsert
* @since 3.10.0
* @see UpdateOptions#upsert(boolean)
*/
public static Bson setOnInsert(final Bson value) {
return new SimpleBsonKeyValue("$setOnInsert", value);
}
/**
* Creates an update that sets the value of the field with the given name to the given value, but only if the update is an upsert that
* results in an insert of a document.
*
* @param fieldName the non-null field name
* @param value the value, which may be null
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/setOnInsert/ $setOnInsert
* @see UpdateOptions#upsert(boolean)
*/
public static Bson setOnInsert(final String fieldName, @Nullable final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$setOnInsert");
}
/**
* Creates an update that renames a field.
*
* @param fieldName the non-null field name
* @param newFieldName the non-null new field name
* @return the update
* @mongodb.driver.manual reference/operator/update/rename/ $rename
*/
public static Bson rename(final String fieldName, final String newFieldName) {
notNull("newFieldName", newFieldName);
return new SimpleUpdate<>(fieldName, newFieldName, "$rename");
}
/**
* Creates an update that increments the value of the field with the given name by the given value.
*
* @param fieldName the non-null field name
* @param number the value
* @return the update
* @mongodb.driver.manual reference/operator/update/inc/ $inc
*/
public static Bson inc(final String fieldName, final Number number) {
notNull("number", number);
return new SimpleUpdate<>(fieldName, number, "$inc");
}
/**
* Creates an update that multiplies the value of the field with the given name by the given number.
*
* @param fieldName the non-null field name
* @param number the non-null number
* @return the update
* @mongodb.driver.manual reference/operator/update/mul/ $mul
*/
public static Bson mul(final String fieldName, final Number number) {
notNull("number", number);
return new SimpleUpdate<>(fieldName, number, "$mul");
}
/**
* Creates an update that sets the value of the field to the given value if the given value is less than the current value of the
* field.
*
* @param fieldName the non-null field name
* @param value the value
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/min/ $min
*/
public static Bson min(final String fieldName, final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$min");
}
/**
* Creates an update that sets the value of the field to the given value if the given value is greater than the current value of the
* field.
*
* @param fieldName the non-null field name
* @param value the value
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/min/ $min
*/
public static Bson max(final String fieldName, final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$max");
}
/**
* Creates an update that sets the value of the field to the current date as a BSON date.
*
* @param fieldName the non-null field name
* @return the update
* @mongodb.driver.manual reference/operator/update/currentDate/ $currentDate
* @mongodb.driver.manual reference/bson-types/#date Date
*/
public static Bson currentDate(final String fieldName) {
return new SimpleUpdate<>(fieldName, true, "$currentDate");
}
/**
* Creates an update that sets the value of the field to the current date as a BSON timestamp.
*
* @param fieldName the non-null field name
* @return the update
* @mongodb.driver.manual reference/operator/update/currentDate/ $currentDate
* @mongodb.driver.manual reference/bson-types/#document-bson-type-timestamp Timestamp
*/
public static Bson currentTimestamp(final String fieldName) {
return new SimpleUpdate<>(fieldName, new BsonDocument("$type", new BsonString("timestamp")), "$currentDate");
}
/**
* Creates an update that adds the given value to the array value of the field with the given name, unless the value is
* already present, in which case it does nothing
*
* @param fieldName the non-null field name
* @param value the value, which may be null
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/addToSet/ $addToSet
*/
public static Bson addToSet(final String fieldName, @Nullable final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$addToSet");
}
/**
* Creates an update that adds each of the given values to the array value of the field with the given name, unless the value is
* already present, in which case it does nothing
*
* @param fieldName the non-null field name
* @param values the values
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/addToSet/ $addToSet
*/
public static Bson addEachToSet(final String fieldName, final List values) {
return new WithEachUpdate<>(fieldName, values, "$addToSet");
}
/**
* Creates an update that adds the given value to the array value of the field with the given name.
*
* @param fieldName the non-null field name
* @param value the value, which may be null
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/push/ $push
*/
public static Bson push(final String fieldName, @Nullable final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$push");
}
/**
* Creates an update that adds each of the given values to the array value of the field with the given name.
*
* @param fieldName the non-null field name
* @param values the values
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/push/ $push
*/
public static Bson pushEach(final String fieldName, final List values) {
return new PushUpdate<>(fieldName, values, new PushOptions());
}
/**
* Creates an update that adds each of the given values to the array value of the field with the given name, applying the given
* options for positioning the pushed values, and then slicing and/or sorting the array.
*
* @param fieldName the non-null field name
* @param values the values
* @param options the non-null push options
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/push/ $push
*/
public static Bson pushEach(final String fieldName, final List values, final PushOptions options) {
return new PushUpdate<>(fieldName, values, options);
}
/**
* Creates an update that removes all instances of the given value from the array value of the field with the given name.
*
* @param fieldName the non-null field name
* @param value the value, which may be null
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/pull/ $pull
*/
public static Bson pull(final String fieldName, @Nullable final TItem value) {
return new SimpleUpdate<>(fieldName, value, "$pull");
}
/**
* Creates an update that removes from an array all elements that match the given filter.
*
* @param filter the query filter
* @return the update
* @mongodb.driver.manual reference/operator/update/pull/ $pull
*/
public static Bson pullByFilter(final Bson filter) {
return new Bson() {
@Override
public BsonDocument toBsonDocument(final Class tDocumentClass, final CodecRegistry codecRegistry) {
BsonDocumentWriter writer = new BsonDocumentWriter(new BsonDocument());
writer.writeStartDocument();
writer.writeName("$pull");
encodeValue(writer, filter, codecRegistry);
writer.writeEndDocument();
return writer.getDocument();
}
};
}
/**
* Creates an update that removes all instances of the given values from the array value of the field with the given name.
*
* @param fieldName the non-null field name
* @param values the values
* @param the value type
* @return the update
* @mongodb.driver.manual reference/operator/update/pull/ $pull
*/
public static Bson pullAll(final String fieldName, final List values) {
return new PullAllUpdate<>(fieldName, values);
}
/**
* Creates an update that pops the first element of an array that is the value of the field with the given name.
*
* @param fieldName the non-null field name
* @return the update
* @mongodb.driver.manual reference/operator/update/pop/ $pop
*/
public static Bson popFirst(final String fieldName) {
return new SimpleUpdate<>(fieldName, -1, "$pop");
}
/**
* Creates an update that pops the last element of an array that is the value of the field with the given name.
*
* @param fieldName the non-null field name
* @return the update
* @mongodb.driver.manual reference/operator/update/pop/ $pop
*/
public static Bson popLast(final String fieldName) {
return new SimpleUpdate<>(fieldName, 1, "$pop");
}
/**
* Creates an update that performs a bitwise and between the given integer value and the integral value of the field with the given
* name.
*
* @param fieldName the field name
* @param value the value
* @return the update
*/
public static Bson bitwiseAnd(final String fieldName, final int value) {
return createBitUpdateDocument(fieldName, "and", value);
}
/**
* Creates an update that performs a bitwise and between the given long value and the integral value of the field with the given name.
*
* @param fieldName the field name
* @param value the value
* @return the update
* @mongodb.driver.manual reference/operator/update/bit/ $bit
*/
public static Bson bitwiseAnd(final String fieldName, final long value) {
return createBitUpdateDocument(fieldName, "and", value);
}
/**
* Creates an update that performs a bitwise or between the given integer value and the integral value of the field with the given
* name.
*
* @param fieldName the field name
* @param value the value
* @return the update
* @mongodb.driver.manual reference/operator/update/bit/ $bit
*/
public static Bson bitwiseOr(final String fieldName, final int value) {
return createBitUpdateDocument(fieldName, "or", value);
}
/**
* Creates an update that performs a bitwise or between the given long value and the integral value of the field with the given name.
*
* @param fieldName the field name
* @param value the value
* @return the update
* @mongodb.driver.manual reference/operator/update/bit/ $bit
*/
public static Bson bitwiseOr(final String fieldName, final long value) {
return createBitUpdateDocument(fieldName, "or", value);
}
/**
* Creates an update that performs a bitwise xor between the given integer value and the integral value of the field with the given
* name.
*
* @param fieldName the field name
* @param value the value
* @return the update
*/
public static Bson bitwiseXor(final String fieldName, final int value) {
return createBitUpdateDocument(fieldName, "xor", value);
}
/**
* Creates an update that performs a bitwise xor between the given long value and the integral value of the field with the given name.
*
* @param fieldName the field name
* @param value the value
* @return the update
*/
public static Bson bitwiseXor(final String fieldName, final long value) {
return createBitUpdateDocument(fieldName, "xor", value);
}
private static Bson createBitUpdateDocument(final String fieldName, final String bitwiseOperator, final int value) {
return createBitUpdateDocument(fieldName, bitwiseOperator, new BsonInt32(value));
}
private static Bson createBitUpdateDocument(final String fieldName, final String bitwiseOperator, final long value) {
return createBitUpdateDocument(fieldName, bitwiseOperator, new BsonInt64(value));
}
private static Bson createBitUpdateDocument(final String fieldName, final String bitwiseOperator, final BsonValue value) {
return new BsonDocument("$bit", new BsonDocument(fieldName, new BsonDocument(bitwiseOperator, value)));
}
private static class SimpleBsonKeyValue implements Bson {
private final String fieldName;
private final Bson value;
SimpleBsonKeyValue(final String fieldName, final Bson value) {
this.fieldName = notNull("fieldName", fieldName);
this.value = notNull("value", value);
}
@Override
public BsonDocument toBsonDocument(final Class tDocumentClass, final CodecRegistry codecRegistry) {
BsonDocumentWriter writer = new BsonDocumentWriter(new BsonDocument());
writer.writeStartDocument();
writer.writeName(fieldName);
encodeValue(writer, value, codecRegistry);
writer.writeEndDocument();
return writer.getDocument();
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SimpleBsonKeyValue that = (SimpleBsonKeyValue) o;
if (!fieldName.equals(that.fieldName)) {
return false;
}
return value.equals(that.value);
}
@Override
public int hashCode() {
int result = fieldName.hashCode();
result = 31 * result + value.hashCode();
return result;
}
@Override
public String toString() {
return "SimpleBsonKeyValue{"
+ "fieldName='" + fieldName + '\''
+ ", value=" + value
+ '}';
}
}
private static class SimpleUpdate implements Bson {
private final String fieldName;
private final TItem value;
private final String operator;
SimpleUpdate(final String fieldName, final TItem value, final String operator) {
this.fieldName = notNull("fieldName", fieldName);
this.value = value;
this.operator = operator;
}
@Override
public BsonDocument toBsonDocument(final Class tDocumentClass, final CodecRegistry codecRegistry) {
BsonDocumentWriter writer = new BsonDocumentWriter(new BsonDocument());
writer.writeStartDocument();
writer.writeName(operator);
writer.writeStartDocument();
writer.writeName(fieldName);
encodeValue(writer, value, codecRegistry);
writer.writeEndDocument();
writer.writeEndDocument();
return writer.getDocument();
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SimpleUpdate> that = (SimpleUpdate>) o;
if (!fieldName.equals(that.fieldName)) {
return false;
}
if (!Objects.equals(value, that.value)) {
return false;
}
return Objects.equals(operator, that.operator);
}
@Override
public int hashCode() {
int result = fieldName.hashCode();
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (operator != null ? operator.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Update{"
+ "fieldName='" + fieldName + '\''
+ ", operator='" + operator + '\''
+ ", value=" + value
+ '}';
}
}
private static class WithEachUpdate implements Bson {
private final String fieldName;
private final List values;
private final String operator;
WithEachUpdate(final String fieldName, final List values, final String operator) {
this.fieldName = notNull("fieldName", fieldName);
this.values = notNull("values", values);
this.operator = operator;
}
@Override
public BsonDocument toBsonDocument(final Class tDocumentClass, final CodecRegistry codecRegistry) {
BsonDocumentWriter writer = new BsonDocumentWriter(new BsonDocument());
writer.writeStartDocument();
writer.writeName(operator);
writer.writeStartDocument();
writer.writeName(fieldName);
writer.writeStartDocument();
writer.writeStartArray("$each");
for (TItem value : values) {
encodeValue(writer, value, codecRegistry);
}
writer.writeEndArray();
writeAdditionalFields(writer, tDocumentClass, codecRegistry);
writer.writeEndDocument();
writer.writeEndDocument();
writer.writeEndDocument();
return writer.getDocument();
}
protected void writeAdditionalFields(final BsonDocumentWriter writer, final Class tDocumentClass,
final CodecRegistry codecRegistry) {
}
protected String additionalFieldsToString() {
return "";
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
WithEachUpdate> that = (WithEachUpdate>) o;
if (!fieldName.equals(that.fieldName)) {
return false;
}
if (!values.equals(that.values)) {
return false;
}
return Objects.equals(operator, that.operator);
}
@Override
public int hashCode() {
int result = fieldName.hashCode();
result = 31 * result + values.hashCode();
result = 31 * result + (operator != null ? operator.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Each Update{"
+ "fieldName='" + fieldName + '\''
+ ", operator='" + operator + '\''
+ ", values=" + values
+ additionalFieldsToString()
+ '}';
}
}
private static class PushUpdate extends WithEachUpdate {
private final PushOptions options;
PushUpdate(final String fieldName, final List values, final PushOptions options) {
super(fieldName, values, "$push");
this.options = notNull("options", options);
}
@Override
protected void writeAdditionalFields(final BsonDocumentWriter writer, final Class tDocumentClass,
final CodecRegistry codecRegistry) {
Integer position = options.getPosition();
if (position != null) {
writer.writeInt32("$position", position);
}
Integer slice = options.getSlice();
if (slice != null) {
writer.writeInt32("$slice", slice);
}
Integer sort = options.getSort();
if (sort != null) {
writer.writeInt32("$sort", sort);
} else {
Bson sortDocument = options.getSortDocument();
if (sortDocument != null) {
writer.writeName("$sort");
encodeValue(writer, sortDocument, codecRegistry);
}
}
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
PushUpdate> that = (PushUpdate>) o;
return options.equals(that.options);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + options.hashCode();
return result;
}
@Override
protected String additionalFieldsToString() {
return ", options=" + options;
}
}
private static class PullAllUpdate implements Bson {
private final String fieldName;
private final List values;
PullAllUpdate(final String fieldName, final List values) {
this.fieldName = notNull("fieldName", fieldName);
this.values = notNull("values", values);
}
@Override
public BsonDocument toBsonDocument(final Class tDocumentClass, final CodecRegistry codecRegistry) {
BsonDocumentWriter writer = new BsonDocumentWriter(new BsonDocument());
writer.writeStartDocument();
writer.writeName("$pullAll");
writer.writeStartDocument();
writer.writeName(fieldName);
writer.writeStartArray();
for (TItem value : values) {
encodeValue(writer, value, codecRegistry);
}
writer.writeEndArray();
writer.writeEndDocument();
writer.writeEndDocument();
return writer.getDocument();
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PullAllUpdate> that = (PullAllUpdate>) o;
if (!fieldName.equals(that.fieldName)) {
return false;
}
return values.equals(that.values);
}
@Override
public int hashCode() {
int result = fieldName.hashCode();
result = 31 * result + values.hashCode();
return result;
}
@Override
public String toString() {
return "Update{"
+ "fieldName='" + fieldName + '\''
+ ", operator='$pullAll'"
+ ", value=" + values
+ '}';
}
}
private static class CompositeUpdate implements Bson {
private final List extends Bson> updates;
CompositeUpdate(final List extends Bson> updates) {
this.updates = updates;
}
@Override
public BsonDocument toBsonDocument(final Class tDocumentClass, final CodecRegistry codecRegistry) {
BsonDocument document = new BsonDocument();
for (Bson update : updates) {
BsonDocument rendered = update.toBsonDocument(tDocumentClass, codecRegistry);
for (Map.Entry element : rendered.entrySet()) {
if (document.containsKey(element.getKey())) {
BsonDocument currentOperatorDocument = (BsonDocument) element.getValue();
BsonDocument existingOperatorDocument = document.getDocument(element.getKey());
for (Map.Entry currentOperationDocumentElements : currentOperatorDocument.entrySet()) {
existingOperatorDocument.append(currentOperationDocumentElements.getKey(),
currentOperationDocumentElements.getValue());
}
} else {
document.append(element.getKey(), element.getValue());
}
}
}
return document;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CompositeUpdate that = (CompositeUpdate) o;
return Objects.equals(updates, that.updates);
}
@Override
public int hashCode() {
return updates != null ? updates.hashCode() : 0;
}
@Override
public String toString() {
return "Updates{"
+ "updates=" + updates
+ '}';
}
}
private Updates() {
}
}