Browse Source

Polishing

issue/4185-light
Christoph Strobl 8 months ago
parent
commit
1177adb91e
No known key found for this signature in database
GPG Key ID: E6054036D0C37A4B
  1. 5
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java
  2. 4
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java
  3. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/QueryCharacteristic.java
  4. 142
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/QueryCharacteristics.java

5
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java

@ -24,12 +24,12 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.StreamSupport;
import org.bson.BsonBinary; import org.bson.BsonBinary;
import org.bson.BsonBinarySubType; import org.bson.BsonBinarySubType;
import org.bson.BsonNull; import org.bson.BsonNull;
import org.bson.Document; import org.bson.Document;
import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty; import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty;
@ -778,7 +778,8 @@ public class CollectionOptions {
} }
} }
field.append("queries", property.getCharacteristics().map(QueryCharacteristic::toDocument).toList()); field.append("queries", StreamSupport.stream(property.getCharacteristics().spliterator(), false)
.map(QueryCharacteristic::toDocument).toList());
if (!field.containsKey("keyId")) { if (!field.containsKey("keyId")) {
field.append("keyId", BsonNull.VALUE); field.append("keyId", BsonNull.VALUE);

4
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java

@ -1205,8 +1205,8 @@ public class IdentifiableJsonSchemaProperty<T extends JsonSchemaObject> implemen
} }
/** /**
* {@link JsonSchemaProperty} implementation typically wrapping {@link EncryptedJsonSchemaProperty encrypted * {@link JsonSchemaProperty} implementation typically wrapping an {@link EncryptedJsonSchemaProperty encrypted
* properties} to mark them as queryable. * property} to mark it as queryable.
* *
* @author Christoph Strobl * @author Christoph Strobl
* @since 4.5 * @since 4.5

6
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/QueryCharacteristic.java

@ -18,6 +18,9 @@ package org.springframework.data.mongodb.core.schema;
import org.bson.Document; import org.bson.Document;
/** /**
* Defines the specific character of a query that can be executed. Mainly used to define the characteristic of queryable
* encrypted fields.
*
* @author Christoph Strobl * @author Christoph Strobl
* @since 4.5 * @since 4.5
*/ */
@ -28,6 +31,9 @@ public interface QueryCharacteristic {
*/ */
String queryType(); String queryType();
/**
* @return the raw {@link Document} representation of the instance.
*/
default Document toDocument() { default Document toDocument() {
return new Document("queryType", queryType()); return new Document("queryType", queryType());
} }

142
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/QueryCharacteristics.java

@ -22,18 +22,22 @@ import java.util.List;
import org.bson.BsonNull; import org.bson.BsonNull;
import org.bson.Document; import org.bson.Document;
import org.springframework.data.domain.Range; import org.springframework.data.domain.Range;
import org.springframework.data.domain.Range.Bound; import org.springframework.data.domain.Range.Bound;
import org.springframework.data.util.Streamable;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
* Encapsulation of individual {@link QueryCharacteristic query characteristics} used to define queries that can be
* executed when using queryable encryption.
*
* @author Christoph Strobl * @author Christoph Strobl
* @since 4.5 * @since 4.5
*/ */
public class QueryCharacteristics implements Streamable<QueryCharacteristic> { public class QueryCharacteristics implements Iterable<QueryCharacteristic> {
/**
* instance indicating none
*/
private static final QueryCharacteristics NONE = new QueryCharacteristics(Collections.emptyList()); private static final QueryCharacteristics NONE = new QueryCharacteristics(Collections.emptyList());
private final List<QueryCharacteristic> characteristics; private final List<QueryCharacteristic> characteristics;
@ -42,18 +46,36 @@ public class QueryCharacteristics implements Streamable<QueryCharacteristic> {
this.characteristics = characteristics; this.characteristics = characteristics;
} }
/**
* @return marker instance indicating no characteristics have been defined.
*/
public static QueryCharacteristics none() { public static QueryCharacteristics none() {
return NONE; return NONE;
} }
/**
* Create new {@link QueryCharacteristics} from given list of {@link QueryCharacteristic characteristics}.
*
* @param characteristics must not be {@literal null}.
* @return new instance of {@link QueryCharacteristics}.
*/
public static QueryCharacteristics of(List<QueryCharacteristic> characteristics) { public static QueryCharacteristics of(List<QueryCharacteristic> characteristics) {
return new QueryCharacteristics(List.copyOf(characteristics)); return new QueryCharacteristics(List.copyOf(characteristics));
} }
/**
* Create new {@link QueryCharacteristics} from given {@link QueryCharacteristic characteristics}.
*
* @param characteristics must not be {@literal null}.
* @return new instance of {@link QueryCharacteristics}.
*/
public static QueryCharacteristics of(QueryCharacteristic... characteristics) { public static QueryCharacteristics of(QueryCharacteristic... characteristics) {
return new QueryCharacteristics(Arrays.asList(characteristics)); return new QueryCharacteristics(Arrays.asList(characteristics));
} }
/**
* @return the list of {@link QueryCharacteristic characteristics}.
*/
public List<QueryCharacteristic> getCharacteristics() { public List<QueryCharacteristic> getCharacteristics() {
return characteristics; return characteristics;
} }
@ -63,22 +85,50 @@ public class QueryCharacteristics implements Streamable<QueryCharacteristic> {
return this.characteristics.iterator(); return this.characteristics.iterator();
} }
/**
* Create a new {@link RangeQuery range query characteristic} used to define range queries against an encrypted field.
*
* @param <T> targeted field type
* @return new instance of {@link RangeQuery}.
*/
public static <T> RangeQuery<T> range() { public static <T> RangeQuery<T> range() {
return new RangeQuery<>(); return new RangeQuery<>();
} }
/**
* Create a new {@link EqualityQuery equality query characteristic} used to define equality queries against an
* encrypted field.
*
* @param <T> targeted field type
* @return new instance of {@link EqualityQuery}.
*/
public static <T> EqualityQuery<T> equality() { public static <T> EqualityQuery<T> equality() {
return new EqualityQuery<>(null); return new EqualityQuery<>(null);
} }
/**
* {@link QueryCharacteristic} for equality comparison.
*
* @param <T>
* @since 4.5
*/
public static class EqualityQuery<T> implements QueryCharacteristic { public static class EqualityQuery<T> implements QueryCharacteristic {
private final @Nullable Long contention; private final @Nullable Long contention;
/**
* Create new instance of {@link EqualityQuery}.
*
* @param contention can be {@literal null}.
*/
public EqualityQuery(@Nullable Long contention) { public EqualityQuery(@Nullable Long contention) {
this.contention = contention; this.contention = contention;
} }
/**
* @param contention concurrent counter partition factor.
* @return new instance of {@link EqualityQuery}.
*/
public EqualityQuery<T> contention(long contention) { public EqualityQuery<T> contention(long contention) {
return new EqualityQuery<>(contention); return new EqualityQuery<>(contention);
} }
@ -94,64 +144,120 @@ public class QueryCharacteristics implements Streamable<QueryCharacteristic> {
} }
} }
/**
* {@link QueryCharacteristic} for range comparison.
*
* @param <T>
* @since 4.5
*/
public static class RangeQuery<T> implements QueryCharacteristic { public static class RangeQuery<T> implements QueryCharacteristic {
private final @Nullable Range<T> valueRange; private final @Nullable Range<T> valueRange;
private final @Nullable Integer trimFactor; private final @Nullable Integer trimFactor;
private final @Nullable Long sparsity; private final @Nullable Long sparsity;
private final @Nullable Long precision;
private final @Nullable Long contention; private final @Nullable Long contention;
private RangeQuery() { private RangeQuery() {
this(Range.unbounded(), null, null, null); this(Range.unbounded(), null, null, null, null);
} }
/**
* Create new instance of {@link RangeQuery}.
*
* @param valueRange
* @param trimFactor
* @param sparsity
* @param contention
*/
public RangeQuery(@Nullable Range<T> valueRange, @Nullable Integer trimFactor, @Nullable Long sparsity, public RangeQuery(@Nullable Range<T> valueRange, @Nullable Integer trimFactor, @Nullable Long sparsity,
@Nullable Long contention) { @Nullable Long precision, @Nullable Long contention) {
this.valueRange = valueRange; this.valueRange = valueRange;
this.trimFactor = trimFactor; this.trimFactor = trimFactor;
this.sparsity = sparsity; this.sparsity = sparsity;
this.precision = precision;
this.contention = contention; this.contention = contention;
} }
@Override /**
public String queryType() { * @param lower the lower value range boundary for the queryable field.
return "range"; * @return new instance of {@link RangeQuery}.
} */
public RangeQuery<T> min(T lower) { public RangeQuery<T> min(T lower) {
Range<T> range = Range.of(Bound.inclusive(lower), Range<T> range = Range.of(Bound.inclusive(lower),
valueRange != null ? valueRange.getUpperBound() : Bound.unbounded()); valueRange != null ? valueRange.getUpperBound() : Bound.unbounded());
return new RangeQuery<>(range, trimFactor, sparsity, contention); return new RangeQuery<>(range, trimFactor, sparsity, precision, contention);
} }
/**
* @param upper the upper value range boundary for the queryable field.
* @return new instance of {@link RangeQuery}.
*/
public RangeQuery<T> max(T upper) { public RangeQuery<T> max(T upper) {
Range<T> range = Range.of(valueRange != null ? valueRange.getLowerBound() : Bound.unbounded(), Range<T> range = Range.of(valueRange != null ? valueRange.getLowerBound() : Bound.unbounded(),
Bound.inclusive(upper)); Bound.inclusive(upper));
return new RangeQuery<>(range, trimFactor, sparsity, contention); return new RangeQuery<>(range, trimFactor, sparsity, precision, contention);
} }
/**
* @param trimFactor value to control the throughput of concurrent inserts and updates.
* @return new instance of {@link RangeQuery}.
*/
public RangeQuery<T> trimFactor(int trimFactor) { public RangeQuery<T> trimFactor(int trimFactor) {
return new RangeQuery<>(valueRange, trimFactor, sparsity, contention); return new RangeQuery<>(valueRange, trimFactor, sparsity, precision, contention);
} }
/**
* @param sparsity value to control the value density within the index.
* @return new instance of {@link RangeQuery}.
*/
public RangeQuery<T> sparsity(long sparsity) { public RangeQuery<T> sparsity(long sparsity) {
return new RangeQuery<>(valueRange, trimFactor, sparsity, contention); return new RangeQuery<>(valueRange, trimFactor, sparsity, precision, contention);
} }
/**
* @param contention concurrent counter partition factor.
* @return new instance of {@link RangeQuery}.
*/
public RangeQuery<T> contention(long contention) { public RangeQuery<T> contention(long contention) {
return new RangeQuery<>(valueRange, trimFactor, sparsity, contention); return new RangeQuery<>(valueRange, trimFactor, sparsity, precision, contention);
}
/**
* @param precision digits considered comparing floating point numbers.
* @return new instance of {@link RangeQuery}.
*/
public RangeQuery<T> precision(long precision) {
return new RangeQuery<>(valueRange, trimFactor, sparsity, precision, contention);
}
@Override
public String queryType() {
return "range";
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Document toDocument() { public Document toDocument() {
return QueryCharacteristic.super.toDocument().append("contention", contention).append("trimFactor", trimFactor) Document target = QueryCharacteristic.super.toDocument();
.append("sparsity", sparsity).append("min", valueRange.getLowerBound().getValue().orElse((T) BsonNull.VALUE)) if (contention != null) {
.append("max", valueRange.getUpperBound().getValue().orElse((T) BsonNull.VALUE)); target.append("contention", contention);
} }
if (trimFactor != null) {
target.append("trimFactor", trimFactor);
}
if (valueRange != null) {
target.append("min", valueRange.getLowerBound().getValue().orElse((T) BsonNull.VALUE)).append("max",
valueRange.getUpperBound().getValue().orElse((T) BsonNull.VALUE));
}
if (sparsity != null) {
target.append("sparsity", sparsity);
} }
return target;
}
}
} }

Loading…
Cancel
Save