Index Creation
Spring Data MongoDB 可以自动为使用 @Document
做了注解的实体类型创建索引。自 3.0 版本起必须显式启用索引创建,以防集合生命周期和性能影响带来不良影响。在应用程序启动时和在应用程序运行时首次访问实体类型时,将为最初的实体集自动创建索引。
Spring Data MongoDB can automatically create indexes for entity types annotated with @Document
.
Index creation must be explicitly enabled since version 3.0 to prevent undesired effects with collection lifecyle and performance impact.
Indexes are automatically created for the initial entity set on application startup and when accessing an entity type for the first time while the application runs.
我们通常建议显式创建索引以基于应用程序的方式控制索引,因为 Spring Data 无法自动为应用程序正在运行时重建的集合创建索引。
We generally recommend explicit index creation for application-based control of indexes as Spring Data cannot automatically create indexes for collections that were recreated while the application was running.
如果你要利用诸如 @GeoSpatialIndexed
、@TextIndexed
、@CompoundIndex
和 @WildcardIndexed
的 @Indexed
注解,IndexResolver
会提供一个抽象用于编程索引定义创建。你可以使用 IndexOperations
和索引定义来创建索引。索引创建的最理想时间点是在应用程序启动时,特别是在刷新了应用程序上下文之后,这可以通过观察 ContextRefreshedEvent
来触发。此事件可保证上下文完全初始化。请注意,此时其他组件(尤其是 Bean 工厂)可能已访问 MongoDB 数据库。
IndexResolver
provides an abstraction for programmatic index definition creation if you want to make use of @Indexed
annotations such as @GeoSpatialIndexed
, @TextIndexed
, @CompoundIndex
and @WildcardIndexed
.
You can use index definitions with IndexOperations
to create indexes.
A good point in time for index creation is on application startup, specifically after the application context was refreshed, triggered by observing ContextRefreshedEvent
.
This event guarantees that the context is fully initialized.
Note that at this time other components, especially bean factories might have access to the MongoDB database.
IndexResolver
会跳过“Map”类属性,除非使用 @WildcardIndexed
进行了注解,因为_map 键_必须是索引定义的一部分。由于地图的目的是使用动态键和值,因此无法从静态映射元数据中解析出这些键。
Map
-like properties are skipped by the IndexResolver
unless annotated with @WildcardIndexed
because the map key must be part of the index definition. Since the purpose of maps is the usage of dynamic keys and values, the keys cannot be resolved from static mapping metadata.
class MyListener {
@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
.getConverter().getMappingContext();
IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);
resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);
}
}
class MyListener{
@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
.getConverter().getMappingContext();
// consider only entities that are annotated with @Document
mappingContext.getPersistentEntities()
.stream()
.filter(it -> it.isAnnotationPresent(Document.class))
.forEach(it -> {
IndexOperations indexOps = mongoTemplate.indexOps(it.getType());
resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex);
});
}
}
或者,如果你希望在任何组件能够从应用程序中访问你的数据库之前确保索引和集合存在,则可以为 MongoTemplate
声明一个 @Bean
方法,并在返回 MongoTemplate
对象之前包含上面的代码。
Alternatively, if you want to ensure index and collection presence before any component is able to access your database from your application, declare a @Bean
method for MongoTemplate
and include the code from above before returning the MongoTemplate
object.
要开启自动索引创建,请在配置中覆盖 To turn automatic index creation ON please override
|
3.0 版中默认启用了 OFF 自动索引创建。
Automatic index creation is turned OFF by default as of version 3.0.
Compound Indexes
复合索引也受支持。它们是在类级别上定义的,而不是在单个属性上定义的。
Compound indexes are also supported. They are defined at the class level, rather than on individual properties.
复合索引对于提高涉及多个字段条件的查询的性能非常重要。 |
Compound indexes are very important to improve the performance of queries that involve criteria on multiple fields |
以下是一个示例,其中按升序创建 lastName
的复合索引,并且按降序创建 age
的复合索引:
Here’s an example that creates a compound index of lastName
in ascending order and age
in descending order:
package com.mycompany.domain;
@Document
@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
public class Person {
@Id
private ObjectId id;
private Integer age;
private String firstName;
private String lastName;
}
|
Hashed Indexes
哈希索引允许在分片集群内基于哈希进行分片。使用哈希字段值对集合进行分片会导致更加随机的分布。有关详细信息,请参阅 MongoDB Documentation。
Hashed indexes allow hash based sharding within a sharded cluster. Using hashed field values to shard collections results in a more random distribution. For details, refer to the MongoDB Documentation.
以下是一个为 _id
创建哈希索引的示例:
Here’s an example that creates a hashed index for _id
:
@Document
public class DomainType {
@HashIndexed @Id String id;
// ...
}
哈希索引可以创建到其他索引定义旁边,如下所示,在这种情况下,将创建这两个索引:
Hashed indexes can be created next to other index definitions like shown below, in that case both indices are created:
@Document
public class DomainType {
@Indexed
@HashIndexed
String value;
// ...
}
如果上面的示例过于冗长,则复合注释可减少需要在属性上声明的注释数量:
In case the example above is too verbose, a compound annotation allows to reduce the number of annotations that need to be declared on a property:
@Document
public class DomainType {
@IndexAndHash(name = "idx...") 1
String value;
// ...
}
@Indexed
@HashIndexed
@Retention(RetentionPolicy.RUNTIME)
public @interface IndexAndHash {
@AliasFor(annotation = Indexed.class, attribute = "name") 1
String name() default "";
}
1 | Potentially register an alias for certain attributes of the meta annotation. |
尽管通过注释创建索引对许多方案来说很方便,但应通过 Although index creation via annotations comes in handy for many scenarios cosider taking over more control by setting up indices manually via
|
Wildcard Indexes
`WildcardIndex`是一种索引,可以根据给定的(通配符)模式包含所有字段或特定字段。有关详细信息,请参阅 MongoDB Documentation。
A WildcardIndex
is an index that can be used to include all fields or specific ones based a given (wildcard) pattern.
For details, refer to the MongoDB Documentation.
可以使用 IndexOperations
通过 WildcardIndex
以编程方式设置索引。
The index can be set up programmatically using WildcardIndex
via IndexOperations
.
mongoOperations
.indexOps(User.class)
.ensureIndex(new WildcardIndex("userMetadata"));
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
@WildcardIndex
注释允许声明性索引设置,该索引设置既可与文档类型一起使用,也可与属性一起使用。
The @WildcardIndex
annotation allows a declarative index setup that can used either with a document type or property.
如果放置在根级别域实体(一个带有 @Document
注释的实体)类型上,则索引解析器将为其创建通配符索引。
If placed on a type that is a root level domain entity (one annotated with @Document
) , the index resolver will create a
wildcard index for it.
@Document
@WildcardIndexed
public class Product {
// …
}
db.product.createIndex({ "$**" : 1 },{})
wildcardProjection
可用于指定索引中要包括/排除的键。
The wildcardProjection
can be used to specify keys to in-/exclude in the index.
wildcardProjection
@Document
@WildcardIndexed(wildcardProjection = "{ 'userMetadata.age' : 0 }")
public class User {
private @Id String id;
private UserMetadata userMetadata;
}
db.user.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "userMetadata.age" : 0 }
}
)
还可以通过将注释直接添加到字段来表示通配符索引。请注意,嵌套路径(如属性)不允许使用 wildcardProjection
。在创建索引期间会忽略在用 @WildcardIndexed
注释的类型上的投影。
Wildcard indexes can also be expressed by adding the annotation directly to the field.
Please note that wildcardProjection
is not allowed on nested paths such as properties.
Projections on types annotated with @WildcardIndexed
are omitted during index creation.
@Document
public class User {
private @Id String id;
@WildcardIndexed
private UserMetadata userMetadata;
}
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
Text Indexes
对于 MongoDB v.2.4,默认情况下禁用文本索引功能。 |
The text index feature is disabled by default for MongoDB v.2.4. |
创建文本索引允许将几个字段累积到可搜索全文索引中。每个集合只能有一个文本索引,因此标有 @TextIndexed
的所有字段都合并到此索引中。可以对属性进行加权以影响文档的排名结果分数。文本索引的默认语言为英语。要更改默认语言,请将 language
属性设置为所需的任何语言(例如,@Document(language="spanish")
)。使用名为 language
或 @Language
的属性允许为每个文档定义语言替代。以下示例显示了如何创建文本索引并将语言设置为西班牙语:
Creating a text index allows accumulating several fields into a searchable full-text index.
It is only possible to have one text index per collection, so all fields marked with @TextIndexed
are combined into this index.
Properties can be weighted to influence the document score for ranking results.
The default language for the text index is English.To change the default language, set the language
attribute to whichever language you want (for example,@Document(language="spanish")
).
Using a property called language
or @Language
lets you define a language override on a per-document base.
The following example shows how to created a text index and set the language to Spanish:
@Document(language = "spanish")
class SomeEntity {
@TextIndexed String foo;
@Language String lang;
Nested nested;
}
class Nested {
@TextIndexed(weight=5) String bar;
String roo;
}