
software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest Maven / Gradle / Ivy
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.enhanced.dynamodb.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import software.amazon.awssdk.annotations.NotThreadSafe;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Expression;
import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.utils.Validate;
/**
* Defines parameters used to when scanning a DynamoDb table or index using the scan() operation (such as
* {@link DynamoDbTable#scan(ScanEnhancedRequest)}).
*
* All parameters are optional.
*/
@SdkPublicApi
@ThreadSafe
public final class ScanEnhancedRequest {
private final Map exclusiveStartKey;
private final Integer limit;
private final Boolean consistentRead;
private final Expression filterExpression;
private final List attributesToProject;
private final Integer segment;
private final Integer totalSegments;
private ScanEnhancedRequest(Builder builder) {
this.exclusiveStartKey = builder.exclusiveStartKey;
this.limit = builder.limit;
this.segment = builder.segment;
this.totalSegments = builder.totalSegments;
this.consistentRead = builder.consistentRead;
this.filterExpression = builder.filterExpression;
this.attributesToProject = builder.attributesToProject != null
? Collections.unmodifiableList(builder.attributesToProject)
: null;
}
/**
* Creates a newly initialized builder for a request object.
*/
public static Builder builder() {
return new Builder();
}
/**
* Returns a builder initialized with all existing values on the request object.
*/
public Builder toBuilder() {
return builder().exclusiveStartKey(exclusiveStartKey)
.limit(limit)
.consistentRead(consistentRead)
.filterExpression(filterExpression)
.addNestedAttributesToProject(attributesToProject);
}
/**
* Returns the value of the exclusive start key set on this request object, or null if it doesn't exist.
*/
public Map exclusiveStartKey() {
return exclusiveStartKey;
}
/**
* Returns the value of limit set on this request object, or null if it doesn't exist.
*/
public Integer limit() {
return limit;
}
/**
* Returns the value of segment set on this request object, or null if it doesn't exist.
*/
public Integer segment() {
return segment;
}
/**
* Returns the value of totalSegments set on this request object, or null if it doesn't exist.
*/
public Integer totalSegments() {
return totalSegments;
}
/**
* Returns the value of consistent read, or false if it has not been set.
*/
public Boolean consistentRead() {
return consistentRead;
}
/**
* Returns the return result filter {@link Expression} set on this request object, or null if it doesn't exist.
*/
public Expression filterExpression() {
return filterExpression;
}
/**
* Returns the list of projected attributes on this request object, or an null if no projection is specified.
* Nested attributes are represented using the '.' separator. Example : foo.bar is represented as "foo.bar" which is
* indistinguishable from a non-nested attribute with the name "foo.bar".
* Use {@link #nestedAttributesToProject} if you have a use-case that requires discrimination between these two cases.
*/
public List attributesToProject() {
return attributesToProject != null ?
attributesToProject.stream().map(item -> String.join(".", item.elements()))
.collect(Collectors.toList()) : null;
}
/**
* Returns the list of projected attribute names, in the form of {@link NestedAttributeName} objects,
* for this request object, or null if no projection is specified.
* Refer {@link NestedAttributeName}
*/
public List nestedAttributesToProject() {
return attributesToProject;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ScanEnhancedRequest scan = (ScanEnhancedRequest) o;
if (exclusiveStartKey != null ? ! exclusiveStartKey.equals(scan.exclusiveStartKey) :
scan.exclusiveStartKey != null) {
return false;
}
if (limit != null ? ! limit.equals(scan.limit) : scan.limit != null) {
return false;
}
if (segment != null ? ! segment.equals(scan.segment) : scan.segment != null) {
return false;
}
if (totalSegments != null ? ! totalSegments.equals(scan.totalSegments) : scan.totalSegments != null) {
return false;
}
if (consistentRead != null ? ! consistentRead.equals(scan.consistentRead) : scan.consistentRead != null) {
return false;
}
if (attributesToProject != null
? !attributesToProject.equals(scan.attributesToProject) : scan.attributesToProject != null) {
return false;
}
return filterExpression != null ? filterExpression.equals(scan.filterExpression) : scan.filterExpression == null;
}
@Override
public int hashCode() {
int result = exclusiveStartKey != null ? exclusiveStartKey.hashCode() : 0;
result = 31 * result + (limit != null ? limit.hashCode() : 0);
result = 31 * result + (segment != null ? segment.hashCode() : 0);
result = 31 * result + (totalSegments != null ? totalSegments.hashCode() : 0);
result = 31 * result + (consistentRead != null ? consistentRead.hashCode() : 0);
result = 31 * result + (filterExpression != null ? filterExpression.hashCode() : 0);
result = 31 * result + (attributesToProject != null ? attributesToProject.hashCode() : 0);
return result;
}
/**
* A builder that is used to create a request with the desired parameters.
*/
@NotThreadSafe
public static final class Builder {
private Map exclusiveStartKey;
private Integer limit;
private Boolean consistentRead;
private Expression filterExpression;
private List attributesToProject;
private Integer segment;
private Integer totalSegments;
private Builder() {
}
/**
* The primary key of the first item that this operation will evaluate. By default, the operation will evaluate
* the whole dataset. If used, normally this parameter is populated with the value that was returned for
* {@link Page#lastEvaluatedKey()} in the previous operation.
*
* @param exclusiveStartKey the primary key value where DynamoDb should start to evaluate items
* @return a builder of this type
*/
public Builder exclusiveStartKey(Map exclusiveStartKey) {
this.exclusiveStartKey = exclusiveStartKey != null ? new HashMap<>(exclusiveStartKey) : null;
return this;
}
/**
* Sets a limit on how many items to evaluate in the scan. If not set, the operation uses
* the maximum values allowed.
*
* Note:The limit does not refer to the number of items to return, but how many items
* the database should evaluate while executing the scan. Use limit together with {@link Page#lastEvaluatedKey()}
* and {@link #exclusiveStartKey} in subsequent scan calls to evaluate limit items per call.
*
* @param limit the maximum number of items to evalute
* @return a builder of this type
*/
public Builder limit(Integer limit) {
this.limit = limit;
return this;
}
/**
* For a parallel Scan request, Segment identifies an individual segment to be scanned by an application worker.
*
* Note:Segment IDs are zero-based, so the first segment is always 0. For example, if you want to use four
* application threads to scan a table or an index, then the first thread specifies a Segment value of 0, the second
* thread specifies 1, and so on.
*
* The value for Segment must be greater than or equal to 0, and less than the value provided for TotalSegments.
*
* If you provide Segment, you must also provide TotalSegments.
*
* @param segment identifies an individual segment to be scanned
* @return a builder of this type
*/
public Builder segment(Integer segment) {
this.segment = segment;
return this;
}
/**
* For a parallel Scan request, TotalSegments represents the total number of segments into
* which the Scan operation will be divided.
*
* Note:If you do not specify this value, the TotalSegements is effectively 1 and Scan operation
* will be sequential rather than parallel.
*
* If you specify TotalSegments, you must also specify Segment.
*
* If you specify TotalSegments of 2 and above, you can create separate thread for each segment and scan items
* in parallel across segments from multiple threads.
*
* @param totalSegments the total number of segments to divide the table.
* @return a builder of this type
*/
public Builder totalSegments(Integer totalSegments) {
this.totalSegments = totalSegments;
return this;
}
/**
* Determines the read consistency model: If set to true, the operation uses strongly consistent reads; otherwise,
* the operation uses eventually consistent reads.
*
* By default, the value of this property is set to false.
*
* @param consistentRead sets consistency model of the operation to use strong consistency if true
* @return a builder of this type
*/
public Builder consistentRead(Boolean consistentRead) {
this.consistentRead = consistentRead;
return this;
}
/**
* Refines the scan results by applying the filter expression on the results returned
* from the scan and discards items that do not match. See {@link Expression} for examples
* and constraints.
*
* Note: Using the filter expression does not reduce the cost of the scan, since it is applied
* after the database has found matching items.
*
* @param filterExpression an expression that filters results of evaluating the scan
* @return a builder of this type
*/
public Builder filterExpression(Expression filterExpression) {
this.filterExpression = filterExpression;
return this;
}
/**
*
* Sets a collection of the attribute names to be retrieved from the database. These attributes can include
* scalars, sets, or elements of a JSON document.
*
* If no attribute names are specified, then all attributes will be returned. If any of the requested attributes
* are not found, they will not appear in the result.
*
* If there are nested attributes, use any of the addNestedAttributesToProject methods, such as
* {@link #addNestedAttributesToProject(NestedAttributeName...)}.
*
* For more information, see Accessing Item Attributes in the Amazon DynamoDB Developer Guide.
*
*
* @param attributesToProject A collection of the attributes names to be retrieved from the database.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder attributesToProject(Collection attributesToProject) {
if (this.attributesToProject != null) {
this.attributesToProject.clear();
}
if (attributesToProject != null) {
addNestedAttributesToProject(new ArrayList<>(attributesToProject).stream()
.map(NestedAttributeName::create).collect(Collectors.toList()));
}
return this;
}
/**
*
* Sets one or more attribute names to be retrieved from the database. These attributes can include
* scalars, sets, or elements of a JSON document.
*
* If no attribute names are specified, then all attributes will be returned. If any of the requested attributes
* are not found, they will not appear in the result.
*
* If there are nested attributes, use any of the addNestedAttributesToProject methods, such as
* {@link #addNestedAttributesToProject(NestedAttributeName...)}.
*
* For more information, see Accessing Item Attributes in the Amazon DynamoDB Developer Guide.
*
* @param attributesToProject One or more attributes names to be retrieved from the database.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder attributesToProject(String... attributesToProject) {
return attributesToProject(Arrays.asList(attributesToProject));
}
/**
*
Adds a single attribute name to be retrieved from the database. This attribute can include
* scalars, sets, or elements of a JSON document.
*
If there are nested attributes, use any of the addNestedAttributesToProject methods, such as
* {@link #addNestedAttributesToProject(NestedAttributeName...)}.
*
* @param attributeToProject An additional single attribute name to be retrieved from the database.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder addAttributeToProject(String attributeToProject) {
if (attributeToProject != null) {
addNestedAttributesToProject(NestedAttributeName.create(attributeToProject));
}
return this;
}
/**
* Adds a collection of nested attributes to be retrieved from the database. These attributes can include
* scalars, sets, or elements of a JSON document.
*
* This method is additive, so calling it multiple times will add to the list of nested attribute names.
* @see NestedAttributeName
*
* @param nestedAttributeNames A collection of attributes to be retrieved from the database.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder addNestedAttributesToProject(Collection nestedAttributeNames) {
if (nestedAttributeNames != null) {
Validate.noNullElements(nestedAttributeNames,
"nestedAttributeNames list must not contain null elements");
if (attributesToProject == null) {
this.attributesToProject = new ArrayList<>(nestedAttributeNames);
} else {
this.attributesToProject.addAll(nestedAttributeNames);
}
}
return this;
}
/**
* Adds a collection of nested attributes to be retrieved from the database. These attributes can include
* scalars, sets, or elements of a JSON document.
*
* This method is additive, so calling it multiple times will add to the list of nested attribute names.
* @see NestedAttributeName
*
* @param nestedAttributeNames A collection of attributes to be retrieved from the database.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder addNestedAttributesToProject(NestedAttributeName... nestedAttributeNames) {
addNestedAttributesToProject(Arrays.asList(nestedAttributeNames));
return this;
}
/**
* Adds a single nested attribute to be retrieved from the database. The attribute can include
* scalars, sets, or elements of a JSON document.
*
* This method is additive, so calling it multiple times will add to the list of nested attribute names.
* @see NestedAttributeName
*
*
* @param nestedAttributeName A single attribute name to be retrieved from the database.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder addNestedAttributeToProject(NestedAttributeName nestedAttributeName) {
if (nestedAttributeName != null) {
addNestedAttributesToProject(Arrays.asList(nestedAttributeName));
}
return this;
}
public ScanEnhancedRequest build() {
return new ScanEnhancedRequest(this);
}
}
}