索引创建
Spring Data MongoDB 可以自动为带有 .
从版本 3.0 开始,必须显式启用索引创建,以防止对集合生命周期和性能产生不良影响。
在应用程序启动时以及在应用程序运行时首次访问实体类型时,会自动为初始实体集创建索引。@Document
我们通常建议为基于应用程序的索引控制创建显式索引,因为 Spring Data 无法自动为应用程序运行时重新创建的集合创建索引。
IndexResolver
如果要使用 、 和 等注释,则为编程索引定义创建提供抽象。
您可以使用 索引定义 来创建索引。
创建索引的好时机是在应用程序启动时,特别是在刷新应用程序上下文之后,通过观察触发。
此事件保证上下文已完全初始化。
请注意,此时其他组件(尤其是 bean 工厂)可能有权访问 MongoDB 数据库。@Indexed
@GeoSpatialIndexed
@TextIndexed
@CompoundIndex
@WildcardIndexed
IndexOperations
ContextRefreshedEvent
|
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);
});
}
}
或者,如果要在任何组件能够从应用程序访问数据库之前确保索引和集合存在,请在返回对象之前声明一个方法并包含上面的代码。@Bean
MongoTemplate
MongoTemplate
要打开自动索引创建,请在您的配置中覆盖。
|
默认情况下,自动索引创建从 3.0 版开始关闭。 |
复合索引
还支持复合索引。它们是在类级别定义的,而不是在单个属性上定义的。
复合索引对于提高涉及多个字段的条件的查询的性能非常重要 |
下面是一个按升序和降序创建 compound index 的示例:lastName
age
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;
}
|
哈希索引
哈希索引允许在分片集群中进行基于哈希的分片。 使用经过哈希处理的字段值对集合进行分片会导致分布更加随机。 有关详细信息,请参阅 MongoDB 文档。
下面是一个为 创建哈希索引的示例:_id
@Document
public class DomainType {
@HashIndexed @Id String id;
// ...
}
哈希索引可以在其他索引定义旁边创建,如下所示,在这种情况下,两个索引都已创建:
@Document
public class DomainType {
@Indexed
@HashIndexed
String value;
// ...
}
如果上面的示例太冗长,复合 annotation 允许减少需要在 property 上声明的 annotation 数量:
@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 | 可能会为 meta 注解的某些属性注册别名。 |
尽管通过注释创建索引在许多情况下都很方便,但 cosider 通过 .
|
通配符索引
A 是一个索引,可用于包含基于给定(通配符)模式的所有字段或特定字段。
有关详细信息,请参阅 MongoDB 文档。WildcardIndex
可以使用 via 以编程方式设置索引。WildcardIndex
IndexOperations
mongoOperations
.indexOps(User.class)
.ensureIndex(new WildcardIndex("userMetadata"));
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
该注释允许与文档类型或属性一起使用的声明性索引设置。@WildcardIndex
如果放置在作为根级域实体(带有 ) 注释的类型上,则索引解析程序将创建一个
通配符索引。@Document
@Document
@WildcardIndexed
public class Product {
// …
}
db.product.createIndex({ "$**" : 1 },{})
这可用于指定要在索引中 in-/exclude 的键。wildcardProjection
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 }
}
)
通配符索引也可以通过将 annotation 直接添加到字段来表示。
请注意,不允许在嵌套路径(如 properties)上执行此操作。
在索引创建过程中,将省略对 Ancomments 的类型的投影。wildcardProjection
@WildcardIndexed
@Document
public class User {
private @Id String id;
@WildcardIndexed
private UserMetadata userMetadata;
}
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
文本索引
默认情况下,MongoDB v.2.4 的文本索引功能处于禁用状态。 |
创建文本索引允许将多个字段累积到可搜索的全文索引中。
每个集合只能有一个文本索引,因此所有标有的字段都合并到此索引中。
可以对属性进行加权,以影响排名结果的文档分数。
text 索引的默认语言是 English.To 更改默认语言,请将属性设置为所需的任何语言(例如,)。
使用名为 or 的属性,您可以在每个文档的基础上定义语言覆盖。
以下示例显示如何创建文本索引并将语言设置为西班牙语:@TextIndexed
language
@Document(language="spanish")
language
@Language
@Document(language = "spanish")
class SomeEntity {
@TextIndexed String foo;
@Language String lang;
Nested nested;
}
class Nested {
@TextIndexed(weight=5) String bar;
String roo;
}