インデックスの作成
Spring Data MongoDB は、@Document
のアノテーションが付けられたエンティティ型のインデックスを自動的に作成できます。バージョン 3.0 以降では、コレクションのライフサイクルやパフォーマンスへの望ましくない影響を防ぐために、インデックスの作成を明示的に有効にする必要があります。インデックスは、アプリケーションの起動時、およびアプリケーションの実行中に初めてエンティティ型にアクセスしたときに、初期エンティティセットに対して自動的に作成されます。
Spring Data はアプリケーションの実行中に再作成されたコレクションのインデックスを自動的に作成できないため、アプリケーションベースのインデックスの制御には、通常、明示的なインデックスの作成をお勧めします。
IndexResolver
は、@GeoSpatialIndexed
、@TextIndexed
、@CompoundIndex
、@WildcardIndexed
などの @Indexed
アノテーションを使用する場合に、プログラムによるインデックス定義作成の抽象化を提供します。IndexOperations
でインデックス定義を使用してインデックスを作成できます。インデックス作成の適切な時点は、アプリケーションの起動時、特に ContextRefreshedEvent
の監視によってトリガーされてアプリケーションコンテキストがリフレッシュされた後です。このイベントは、コンテキストが完全に初期化されていることを保証します。現時点では、他のコンポーネント、特に Bean ファクトリが MongoDB データベースにアクセスできる可能性があることに注意してください。
|
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
オブジェクトを返す前に上記のコードを含めます。
自動インデックス作成をオンにするには、構成で
|
バージョン 3.0 では、自動インデックス作成はデフォルトでオフになっています。 |
複合インデックス
複合インデックスもサポートされています。これらは、個々のプロパティではなく、クラスレベルで定義されます。
複合インデックスは、複数のフィールドの条件を含むクエリのパフォーマンスを向上させるために非常に重要です。 |
以下は、昇順で 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;
// ...
}
上記の例が冗長すぎる場合は、複合アノテーションを使用して、プロパティで宣言する必要があるアノテーションの数を減らすことができます。
@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 | メタアノテーションの特定の属性のエイリアスを登録する可能性があります。 |
アノテーションによるインデックスの作成は多くのシナリオで便利ですが、
|
ワイルドカードインデックス
WildcardIndex
は、指定された (ワイルドカード) パターンに基づいてすべてのフィールドまたは特定のフィールドを含めるために使用できるインデックスです。詳細は MongoDB ドキュメント (英語) をご参照ください。
インデックスは、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 },{})
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 }
}
)
ワイルドカードインデックスは、フィールドにアノテーションを直接追加することによっても表現できます。wildcardProjection
はプロパティなどのネストされたパスでは許可されないことに注意してください。@WildcardIndexed
アノテーションが付けられた型の射影は、インデックスの作成時に省略されます。
@Document
public class User {
private @Id String id;
@WildcardIndexed
private UserMetadata userMetadata;
}
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
テキストインデックス
MongoDB v.2.4 では、テキストインデックス機能はデフォルトで無効になっています。 |
テキストインデックスを作成すると、複数のフィールドを検索可能なフルテキストインデックスに蓄積できます。コレクションごとに 1 つのテキストインデックスのみを持つことができるため、@TextIndexed
でマークされたすべてのフィールドがこのインデックスに結合されます。プロパティに重みを付けて、ランキング結果のドキュメントスコアに影響を与えることができます。テキストインデックスのデフォルト言語は English.To です。デフォルト言語を変更するには、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;
}