Spring Data MongoDB - インデックス、アノテーション、コンバーター

データ]

  • リンク:/tag/mongodb/[MongoDB]

1概要

このチュートリアルでは、Spring Data MongoDBのいくつかのコア機能、つまりインデックス作成、一般的なアノテーション、およびコンバータについて探ります。

2索引

2.1. __ @インデックス付き

このアノテーションは、MongoDBでフィールドをインデックス付きとしてマークします。

@QueryEntity
@Document
public class User {
    @Indexed
    private String name;

    ...
}

name フィールドにインデックスが付けられました。MongoDBのインデックスを見てみましょう。

db.user.getIndexes();

データベースレベルでは、次のようになります。

----[    {
        "v" : 1,
        "key" : {
             "__id" : 1
         },
        "name" : "__id__",
        "ns" : "test.user"
    },
    {
         "v" : 1,
         "key" : {
             "name" : 1
          },
          "name" : "name",
          "ns" : "test.user"
     }]----

ご覧のとおり、2つのインデックスがあります。そのうちの1つは __ id です。これは @ Id アノテーションのためにデフォルトで作成されたものです。

** 2.2. プログラムによるインデックスの作成

**

プログラムでインデックスを作成することもできます。

mongoOps.indexOps(User.class).
  ensureIndex(new Index().on("name", Direction.ASC));

フィールド name のインデックスを作成したので、結果は前のセクションと同じになります。

2.3. 複合インデックス

MongoDBは複合インデックスをサポートしています。単一のインデックス構造は複数のフィールドへの参照を保持します。

複合インデックスを使用した簡単な例を見てみましょう。

@QueryEntity
@Document
@CompoundIndexes({
    @CompoundIndex(name = "email__age", def = "{'email.id' : 1, 'age': 1}")
})
public class User {
   //}

email フィールドと age フィールドを使用して複合インデックスを作成しました。実際のインデックスをチェックしましょう。

{
    "v" : 1,
    "key" : {
        "email.id" : 1,
        "age" : 1
    },
    "name" : "email__age",
    "ns" : "test.user"
}

DBRef フィールドを @ Index でマークすることはできません。そのフィールドは複合インデックスの一部にしかなれません。

3一般的な注釈

3.1 @トランジェント

ご想像のとおり、この単純な注釈では、フィールドはデータベースに保持されていません。

public class User {

    @Transient
    private Integer yearOfBirth;
   //standard getter and setter

}

設定フィールド yearOfBirth を持つユーザーを挿入しましょう。

User user = new User();
user.setName("Alex");
user.setYearOfBirth(1985);
mongoTemplate.insert(user);

データベースの状態を見ると、ファイル yearOfBirth は保存されていないことがわかります。

{
    "__id" : ObjectId("55d8b30f758fd3c9f374499b"),
    "name" : "Alex",
    "age" : null
}

そのため、クエリして確認すると、

mongoTemplate.findOne(Query.query(Criteria.where("name").is("Alex")), User.class).getYearOfBirth()

結果は null になります。

3.2. @フィールド

@ Field は、JSONドキュメントのフィールドに使用されるキーを示します。

@Field("email")
private EmailAddress emailAddress;

emailAddress は、キー email: を使用してデータベースに保存されます

User user = new User();
user.setName("Brendan");
EmailAddress emailAddress = new EmailAddress();
emailAddress.setValue("[email protected]");
user.setEmailAddress(emailAddress);
mongoTemplate.insert(user);

そしてデータベースの状態:

{
    "__id" : ObjectId("55d076d80bad441ed114419d"),
    "name" : "Brendan",
    "age" : null,
    "email" : {
        "value" : "[email protected]"
    }
}

3.3. @ PersistenceConstructor および @ Value

@ PersistenceConstructor は、パッケージ保護されているものであっても、永続ロジックで使用される主要なコンストラクターとしてコンストラクターをマークします。

コンストラクター引数は、検索された DBObject のキー値に名前でマッピングされます。

User クラスのこのコンストラクタを見てみましょう。

@PersistenceConstructor
public User(String name, @Value("#root.age ?: 0") Integer age, EmailAddress emailAddress) {
    this.name =  name;
    this.age = age;
    this.emailAddress =  emailAddress;
}

ここでは標準のSpring @ Value アノテーションの使用に注目してください。このアノテーションを利用して、ドメインオブジェクトの構築に使用される前に、データベースから取得したキーの値をSpringの式を使用して変換できます。これは非常に強力で非常に便利な機能です。

この例では、 age が設定されていない場合、デフォルトでは 0 に設定されます。

それがどのように機能するのかを見てみましょう。

User user = new User();
user.setName("Alex");
mongoTemplate.insert(user);

私たちのデータベースは以下のようになります。

{
    "__id" : ObjectId("55d074ca0bad45f744a71318"),
    "name" : "Alex",
    "age" : null
}

そのため age フィールドは null ですが、ドキュメントをクエリして age を取得すると

mongoTemplate.findOne(Query.query(Criteria.where("name").is("Alex")), User.class).getAge();

結果は0になります。

4コンバーター

Spring Data MongoDBのもう1つの非常に便利な機能、つまりコンバーター、特に MongoConverter を見てみましょう。

これは、これらのオブジェクトを格納して照会するときに、すべてのJava型を DBObjects にマッピングするために使用されます。

2つの選択肢があります - 以前のバージョンでは MappingMongoConverter – または SimpleMongoConverter のいずれかを使用できます(これはSpring Data MongoDB M3では推奨されず、その機能は MappingMongoConverter に移動されました。

あるいは、私たちは自分のカスタムコンバータを書くことができます。そのためには、 Converter インターフェースを実装し、その実装を MongoConfig. に登録する必要があります。

  • 簡単な例** を見てみましょう。ここでいくつかのJSON出力で見たように、データベースに保存されたすべてのオブジェクトは自動的に保存されるフィールド __class を持ちます。ただし、永続化中にその特定のフィールドをスキップしたい場合は、 MappingMongoConverter を使用してそれを実行できます。

まず、カスタムコンバータの実装です。

@Component
public class UserWriterConverter implements Converter<User, DBObject> {
    @Override
    public DBObject convert(User user) {
        DBObject dbObject = new BasicDBObject();
        dbObject.put("name", user.getName());
        dbObject.put("age", user.getAge());
        if (user.getEmailAddress() != null) {
            DBObject emailDbObject = new BasicDBObject();
            emailDbObject.put("value", user.getEmailAddress().getValue());
            dbObject.put("email", emailDbObject);
        }
        dbObject.removeField("__class");
        return dbObject;
    }
}

ここでフィールドを直接削除することで、 __ class を永続化しないという目標を簡単に達成できることに注目してください。

今度はカスタムコンバータを登録する必要があります。

private List<Converter<?,?>> converters = new ArrayList<Converter<?,?>>();

@Override
public MongoCustomConversions customConversions() {
    converters.add(new UserWriterConverter());
    return new MongoCustomConversions(converters);
}

次のことが必要な場合は、もちろんXML構成でも同じ結果を達成できます。

<bean id="mongoTemplate"
  class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongo" ref="mongo"/>
    <constructor-arg ref="mongoConverter"/>
    <constructor-arg name="databaseName" value="test"/>
</bean>

<mongo:mapping-converter id="mongoConverter" base-package="org.baeldung.converter">
    <mongo:custom-converters base-package="com.baeldung.converter"/>
</mongo:mapping-converter>

それでは、新しいユーザーを保存すると、次のようになります。

User user = new User();
user.setName("Chris");
mongoOps.insert(user);

データベース内の結果の文書には、クラス情報が含まれなくなりました。

{
    "__id" : ObjectId("55cf09790bad4394db84b853"),
    "name" : "Chris",
    "age" : null
}

5結論

このチュートリアルでは、Spring Data MongoDBを操作するためのいくつかの中心的な概念(インデックス作成、一般的なアノテーション、コンバーター)について説明しました。

これらすべての例とコードスニペットの実装は my github project ** にあります。 Eclipseベースのプロジェクトなので、そのままインポートして実行するのは簡単なはずです。

前の投稿:Awaitlityの紹介
次の投稿:Spring SocialでFacebookに二次ログイン