データ]

  • リンク:/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ベースのプロジェクトなので、そのままインポートして実行するのは簡単なはずです。