Browse Source
Spring Data MongoDB uses the @Sharded annotation to identify entities stored in sharded collections. The shard key consists of a single or multiple properties present in every document within the target collection, and is used to distribute them across shards. Spring Data MongoDB will do best effort optimisations for sharded scenarios when using repositories by adding required shard key information, if not already present, to replaceOne filter queries when upserting entities. This may require an additional server round trip to determine the actual value of the current shard key. By setting @Sharded(immutableKey = true) no attempt will be made to check if an entities shard key changed. Please see the MongoDB Documentation for further details and the list below for which operations are eligible to auto include the shard key. * Reactive/CrudRepository.save(...) * Reactive/CrudRepository.saveAll(...) * Reactive/MongoTemplate.save(...) Original pull request: #833.pull/837/head
20 changed files with 1093 additions and 24 deletions
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
/* |
||||
* Copyright 2020 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.mapping; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.bson.Document; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.ObjectUtils; |
||||
|
||||
/** |
||||
* Value object representing an entities <a href="https://docs.mongodb.com/manual/core/sharding-shard-key/">Shard |
||||
* Key</a> used to distribute documents across a sharded MongoDB cluster. |
||||
* <p /> |
||||
* {@link ShardKey#isImmutable() Immutable} shard keys indicate a fixed value that is not updated (see |
||||
* <a href="https://docs.mongodb.com/manual/core/sharding-shard-key/#change-a-document-s-shard-key-value">MongoDB |
||||
* Reference: Change a Document’s Shard Key Value</a>), which allows to skip server round trips in cases where a |
||||
* potential shard key change might have occurred. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 3.0 |
||||
*/ |
||||
public class ShardKey { |
||||
|
||||
private static final ShardKey NONE = new ShardKey(Collections.emptyList(), null, true); |
||||
|
||||
private final List<String> propertyNames; |
||||
private final @Nullable ShardingStrategy shardingStrategy; |
||||
private final boolean immutable; |
||||
|
||||
private ShardKey(List<String> propertyNames, @Nullable ShardingStrategy shardingStrategy, boolean immutable) { |
||||
|
||||
this.propertyNames = propertyNames; |
||||
this.shardingStrategy = shardingStrategy; |
||||
this.immutable = immutable; |
||||
} |
||||
|
||||
/** |
||||
* @return the number of properties used to form the shard key. |
||||
*/ |
||||
public int size() { |
||||
return propertyNames.size(); |
||||
} |
||||
|
||||
/** |
||||
* @return the unmodifiable collection of property names forming the shard key. |
||||
*/ |
||||
public Collection<String> getPropertyNames() { |
||||
return propertyNames; |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} if the shard key of an document does not change. |
||||
* @see <a href="https://docs.mongodb.com/manual/core/sharding-shard-key/#change-a-document-s-shard-key-value">MongoDB |
||||
* Reference: Change a Document’s Shard Key Value</a> |
||||
*/ |
||||
public boolean isImmutable() { |
||||
return immutable; |
||||
} |
||||
|
||||
/** |
||||
* Get the unmapped MongoDB representation of the {@link ShardKey}. |
||||
* |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public Document getDocument() { |
||||
|
||||
Document doc = new Document(); |
||||
for (String field : propertyNames) { |
||||
doc.append(field, shardingValue()); |
||||
} |
||||
return doc; |
||||
} |
||||
|
||||
private Object shardingValue() { |
||||
return ObjectUtils.nullSafeEquals(ShardingStrategy.HASH, shardingStrategy) ? "hash" : 1; |
||||
} |
||||
|
||||
/** |
||||
* {@link ShardKey} indicating no shard key has been defined. |
||||
* |
||||
* @return {@link #NONE} |
||||
*/ |
||||
public static ShardKey none() { |
||||
return NONE; |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link ShardingStrategy#RANGE} shard key. |
||||
* |
||||
* @param propertyNames must not be {@literal null}. |
||||
* @return new instance of {@link ShardKey}. |
||||
*/ |
||||
public static ShardKey range(String... propertyNames) { |
||||
return new ShardKey(Arrays.asList(propertyNames), ShardingStrategy.RANGE, false); |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link ShardingStrategy#RANGE} shard key. |
||||
* |
||||
* @param propertyNames must not be {@literal null}. |
||||
* @return new instance of {@link ShardKey}. |
||||
*/ |
||||
public static ShardKey hash(String... propertyNames) { |
||||
return new ShardKey(Arrays.asList(propertyNames), ShardingStrategy.HASH, false); |
||||
} |
||||
|
||||
/** |
||||
* Turn the given {@link ShardKey} into an {@link #isImmutable() immutable} one. |
||||
* |
||||
* @param shardKey must not be {@literal null}. |
||||
* @return new instance of {@link ShardKey} if the given shard key is not already immutable. |
||||
*/ |
||||
public static ShardKey immutable(ShardKey shardKey) { |
||||
|
||||
if (shardKey.isImmutable()) { |
||||
return shardKey; |
||||
} |
||||
|
||||
return new ShardKey(shardKey.propertyNames, shardKey.shardingStrategy, true); |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
/* |
||||
* Copyright 2020 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.mapping; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Inherited; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.core.annotation.AliasFor; |
||||
import org.springframework.data.annotation.Persistent; |
||||
|
||||
/** |
||||
* The {@link Sharded} annotation provides meta information about the actual distribution of data across multiple |
||||
* machines. The {@link #shardKey()} is used to distribute documents across shards. <br /> |
||||
* Please visit the <a href="https://docs.mongodb.com/manual/sharding/">MongoDB Documentation</a> for more information |
||||
* about requirements and limitations of sharding. <br /> |
||||
* Spring Data will automatically add the shard key to filter queries used for |
||||
* {@link com.mongodb.client.MongoCollection#replaceOne(org.bson.conversions.Bson, Object)} operations triggered by |
||||
* {@code save} operations on {@link org.springframework.data.mongodb.core.MongoOperations} and |
||||
* {@link org.springframework.data.mongodb.core.ReactiveMongoOperations} as well as {@code update/upsert} operation |
||||
* replacing/upserting a single existing document as long as the given |
||||
* {@link org.springframework.data.mongodb.core.query.UpdateDefinition} holds a full copy of the entity. <br /> |
||||
* All other operations that require the presence of the {@literal shard key} in the filter query need to provide the |
||||
* information via the {@link org.springframework.data.mongodb.core.query.Query} parameter when invoking the method. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 3.0 |
||||
*/ |
||||
@Persistent |
||||
@Inherited |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target({ ElementType.TYPE }) |
||||
public @interface Sharded { |
||||
|
||||
/** |
||||
* Alias for {@link #shardKey()}. |
||||
* |
||||
* @return {@literal _id} by default. |
||||
* @see #shardKey() |
||||
*/ |
||||
@AliasFor("shardKey") |
||||
String[] value() default {}; |
||||
|
||||
/** |
||||
* The shard key determines the distribution of the collection’s documents among the cluster’s shards. The shard key |
||||
* is either a single or multiple indexed properties that exist in every document in the collection. <br /> |
||||
* By default the {@literal id} property is used for sharding. <br /> |
||||
* <strong>NOTE</strong> Required indexes will not be created automatically. Use |
||||
* {@link org.springframework.data.mongodb.core.index.Indexed} or |
||||
* {@link org.springframework.data.mongodb.core.index.CompoundIndex} along with enabled |
||||
* {@link org.springframework.data.mongodb.config.MongoConfigurationSupport#autoIndexCreation() auto index creation} |
||||
* or set up them up via |
||||
* {@link org.springframework.data.mongodb.core.index.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)}. |
||||
* |
||||
* @return an empty key by default. Which indicates to use the entities {@literal id} property. |
||||
*/ |
||||
@AliasFor("value") |
||||
String[] shardKey() default {}; |
||||
|
||||
/** |
||||
* The sharding strategy to use for distributing data across sharded clusters. |
||||
* |
||||
* @return {@link ShardingStrategy#RANGE} by default |
||||
*/ |
||||
ShardingStrategy shardingStrategy() default ShardingStrategy.RANGE; |
||||
|
||||
/** |
||||
* As of MongoDB 4.2 it is possible to change the shard key using update. Using immutable shard keys avoids server |
||||
* round trips to obtain an entities actual shard key from the database. |
||||
* |
||||
* @return {@literal false} by default; |
||||
* @see <a href="https://docs.mongodb.com/manual/core/sharding-shard-key/#change-a-document-s-shard-key-value">MongoDB |
||||
* Reference: Change a Document’s Shard Key Value</a> |
||||
*/ |
||||
boolean immutableKey() default false; |
||||
|
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
/* |
||||
* Copyright 2020 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.mapping; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
* @since 3.0 |
||||
*/ |
||||
public enum ShardingStrategy { |
||||
|
||||
/** |
||||
* Ranged sharding involves dividing data into ranges based on the shard key values. Each chunk is then assigned a |
||||
* range based on the shard key values. |
||||
*/ |
||||
RANGE, |
||||
|
||||
/** |
||||
* Hashed Sharding involves computing a hash of the shard key field’s value. Each chunk is then assigned a range based |
||||
* on the hashed shard key values. |
||||
*/ |
||||
HASH |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright 2020 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; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
|
||||
import org.springframework.data.annotation.Id; |
||||
import org.springframework.data.mongodb.core.mapping.Field; |
||||
import org.springframework.data.mongodb.core.mapping.Sharded; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
@Sharded |
||||
public class ShardedEntityWithDefaultShardKey { |
||||
|
||||
private @Id String id; |
||||
|
||||
private String country; |
||||
|
||||
@Field("userid") //
|
||||
private Integer userId; |
||||
|
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright 2020 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; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
|
||||
import org.springframework.data.annotation.Id; |
||||
import org.springframework.data.mongodb.core.mapping.Field; |
||||
import org.springframework.data.mongodb.core.mapping.Sharded; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
@Sharded(shardKey = { "country", "userId" }, immutableKey = true) |
||||
public class ShardedEntityWithNonDefaultImmutableShardKey { |
||||
|
||||
private @Id String id; |
||||
|
||||
private String country; |
||||
|
||||
@Field("userid") //
|
||||
private Integer userId; |
||||
|
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright 2020 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; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
|
||||
import org.springframework.data.annotation.Id; |
||||
import org.springframework.data.mongodb.core.mapping.Field; |
||||
import org.springframework.data.mongodb.core.mapping.Sharded; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
@Sharded(shardKey = { "country", "userId" }) |
||||
public class ShardedEntityWithNonDefaultShardKey { |
||||
|
||||
private @Id String id; |
||||
|
||||
private String country; |
||||
|
||||
@Field("userid") //
|
||||
private Integer userId; |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2020 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; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
|
||||
import org.springframework.data.annotation.Id; |
||||
import org.springframework.data.annotation.Version; |
||||
import org.springframework.data.mongodb.core.mapping.Field; |
||||
import org.springframework.data.mongodb.core.mapping.Sharded; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
@Sharded(shardKey = { "country", "userId" }) |
||||
public class ShardedVersionedEntityWithNonDefaultShardKey { |
||||
|
||||
private @Id String id; |
||||
|
||||
private @Version Long version; |
||||
|
||||
private String country; |
||||
|
||||
@Field("userid") //
|
||||
private Integer userId; |
||||
|
||||
} |
||||
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
/* |
||||
* Copyright 2020 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; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
import org.bson.Document; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.data.mongodb.CodecRegistryProvider; |
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter; |
||||
import org.springframework.data.mongodb.core.convert.MongoConverter; |
||||
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; |
||||
import org.springframework.data.mongodb.core.convert.QueryMapper; |
||||
import org.springframework.data.mongodb.core.convert.UpdateMapper; |
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; |
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; |
||||
import org.springframework.lang.NonNull; |
||||
import org.springframework.lang.Nullable; |
||||
|
||||
import com.mongodb.MongoClientSettings; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
class UpdateOperationsUnitTests { |
||||
|
||||
static final Document SHARD_KEY = new Document("country", "AT").append("userid", "4230"); |
||||
static final Document SOURCE_DOC = appendShardKey(new Document("_id", "id-1")); |
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext(); |
||||
MongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); |
||||
QueryMapper queryMapper = new QueryMapper(mongoConverter); |
||||
UpdateMapper updateMapper = new UpdateMapper(mongoConverter); |
||||
EntityOperations entityOperations = new EntityOperations(mappingContext); |
||||
|
||||
ExtendedQueryOperations queryOperations = new ExtendedQueryOperations(queryMapper, updateMapper, entityOperations, |
||||
MongoClientSettings::getDefaultCodecRegistry); |
||||
|
||||
@Test // DATAMONGO-2341
|
||||
void appliesShardKeyToFilter() { |
||||
|
||||
Document sourceFilter = new Document("name", "kaladin"); |
||||
assertThat(shardedFilter(sourceFilter, ShardedEntityWithNonDefaultShardKey.class, null)) |
||||
.isEqualTo(appendShardKey(sourceFilter)); |
||||
} |
||||
|
||||
@Test |
||||
void applyShardKeyDoesNotAlterSourceFilter() { |
||||
|
||||
Document sourceFilter = new Document("name", "kaladin"); |
||||
shardedFilter(sourceFilter, ShardedEntityWithNonDefaultShardKey.class, null); |
||||
assertThat(sourceFilter).isEqualTo(new Document("name", "kaladin")); |
||||
} |
||||
|
||||
@Test // DATAMONGO-2341
|
||||
void appliesExistingShardKeyToFilter() { |
||||
|
||||
Document sourceFilter = new Document("name", "kaladin"); |
||||
Document existing = new Document("country", "GB").append("userid", "007"); |
||||
|
||||
assertThat(shardedFilter(sourceFilter, ShardedEntityWithNonDefaultShardKey.class, existing)) |
||||
.isEqualTo(new Document(existing).append("name", "kaladin")); |
||||
} |
||||
|
||||
@Test // DATAMONGO-2341
|
||||
void recognizesExistingShardKeyInFilter() { |
||||
|
||||
Document sourceFilter = appendShardKey(new Document("name", "kaladin")); |
||||
|
||||
assertThat(queryOperations.replaceSingleContextFor(SOURCE_DOC).requiresShardKey(sourceFilter, |
||||
entityOf(ShardedEntityWithNonDefaultShardKey.class))).isFalse(); |
||||
} |
||||
|
||||
@Test // DATAMONGO-2341
|
||||
void recognizesIdPropertyAsShardKey() { |
||||
|
||||
Document sourceFilter = new Document("_id", "id-1"); |
||||
|
||||
assertThat(queryOperations.replaceSingleContextFor(SOURCE_DOC).requiresShardKey(sourceFilter, |
||||
entityOf(ShardedEntityWithDefaultShardKey.class))).isFalse(); |
||||
} |
||||
|
||||
@Test // DATAMONGO-2341
|
||||
void returnsMappedShardKey() { |
||||
|
||||
queryOperations.replaceSingleContextFor(SOURCE_DOC) |
||||
.getMappedShardKeyFields(entityOf(ShardedEntityWithDefaultShardKey.class)) |
||||
.containsAll(Arrays.asList("country", "userid")); |
||||
} |
||||
|
||||
@NonNull |
||||
private Document shardedFilter(Document sourceFilter, Class<?> entity, Document existing) { |
||||
return queryOperations.replaceSingleContextFor(SOURCE_DOC).applyShardKey(entity, sourceFilter, existing); |
||||
} |
||||
|
||||
private static Document appendShardKey(Document source) { |
||||
|
||||
Document target = new Document(source); |
||||
target.putAll(SHARD_KEY); |
||||
return target; |
||||
} |
||||
|
||||
MongoPersistentEntity<?> entityOf(Class<?> type) { |
||||
return mappingContext.getPersistentEntity(type); |
||||
} |
||||
|
||||
class ExtendedQueryOperations extends QueryOperations { |
||||
|
||||
ExtendedQueryOperations(QueryMapper queryMapper, UpdateMapper updateMapper, EntityOperations entityOperations, |
||||
CodecRegistryProvider codecRegistryProvider) { |
||||
super(queryMapper, updateMapper, entityOperations, codecRegistryProvider); |
||||
} |
||||
|
||||
@NonNull |
||||
private ExtendedUpdateContext replaceSingleContextFor(Document source) { |
||||
return new ExtendedUpdateContext(MappedDocument.of(source), true); |
||||
} |
||||
|
||||
MongoPersistentEntity<?> entityOf(Class<?> type) { |
||||
return mappingContext.getPersistentEntity(type); |
||||
} |
||||
|
||||
class ExtendedUpdateContext extends UpdateContext { |
||||
|
||||
ExtendedUpdateContext(MappedDocument update, boolean upsert) { |
||||
super(update, upsert); |
||||
} |
||||
|
||||
<T> Document applyShardKey(@Nullable Class<T> domainType, Document filter, @Nullable Document existing) { |
||||
return applyShardKey(entityOf(domainType), filter, existing); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
[[sharding]] |
||||
= Sharding |
||||
|
||||
MongoDB supports large data sets via sharding, a method for distributing data across multiple machines. Please refer to the https://docs.mongodb.com/manual/sharding/[MongoDB Documentation] to learn how to set up a sharded cluster, its requirements and limitations. |
||||
|
||||
Spring Data MongoDB uses the `@Sharded` annotation to identify entities stored in sharded collections as shown below. |
||||
|
||||
==== |
||||
[source, java] |
||||
---- |
||||
@Document("users") |
||||
@Sharded(shardKey = { "country", "userId" }) <1> |
||||
public class User { |
||||
|
||||
@Id |
||||
Long id; |
||||
|
||||
@Field("userid") |
||||
String userId; |
||||
|
||||
String country; |
||||
} |
||||
---- |
||||
<1> The properties of the shard key are mapped to the actual field names. See |
||||
==== |
||||
|
||||
[[sharding.sharded-collections]] |
||||
== Sharded Collections |
||||
|
||||
Spring Data MongoDB does not auto set up sharding for collections nor indexes required for it. The snippet below shows how to do so using the MongoDB client API. |
||||
|
||||
==== |
||||
[source, java] |
||||
---- |
||||
MongoDatabase adminDB = template.getMongoDbFactory() |
||||
.getMongoDatabase("admin"); <1> |
||||
|
||||
adminDB.runCommand(new Document("enableSharding", "db")); <2> |
||||
|
||||
Document shardCmd = new Document("shardCollection", "db.users") <3> |
||||
.append("key", new Document("country", 1).append("userid", 1)); <4> |
||||
|
||||
adminDB.runCommand(shardCmd); |
||||
---- |
||||
<1> Sharding commands need to be run against the _admin_ database. |
||||
<2> Enable sharding for a specific database if necessary. |
||||
<3> Shard a collection within the database having sharding enabled. |
||||
<4> Set the shard key (Range based sharding in this case). |
||||
==== |
||||
|
||||
[[sharding.shard-key]] |
||||
== Shard Key Handling |
||||
|
||||
The shard key consists of a single or multiple properties present in every document within the target collection, and is used to distribute them across shards. |
||||
|
||||
Adding the `@Sharded` annotation to an entity enables Spring Data MongoDB to do best effort optimisations required for sharded scenarios when using repositories. |
||||
This means essentially adding required shard key information, if not already present, to `replaceOne` filter queries when upserting entities. This may require an additional server round trip to determine the actual value of the current shard key. |
||||
|
||||
TIP: By setting `@Sharded(immutableKey = true)` no attempt will be made to check if an entities shard key changed. |
||||
|
||||
Please see the https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#upsert[MongoDB Documentation] for further details and the list below for which operations are eligible for auto include the shard key. |
||||
|
||||
* `Reactive/CrudRepository.save(...)` |
||||
* `Reactive/CrudRepository.saveAll(...)` |
||||
* `Reactive/MongoTemplate.save(...)` |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in new issue