Spring Data MongoDBのクエリガイド

データ]

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

1概要

この記事では、Spring Data MongoDBでさまざまな種類のクエリを作成することに焦点を当てます。

Query クラスと Criteria クラス、自動生成されたクエリメソッド、JSONクエリ、およびQueryDSLを使用したドキュメントのクエリを検討します。

Mavenのセットアップについては、https://www.baeldung.com/spring-data-mongodb-tutorial[Introduction article]をご覧ください。

** 2ドキュメントクエリ

**

Spring DataでMongoDBを照会するためのより一般的な方法の1つは、 Query および Criteria クラスを使用することです。これはネイティブ演算子に非常によく似ています。

2.1. Is

これは単に等式を使用した基準です - それがどのように機能するか見てみましょう。

次の例では、 Eric という名前のユーザーを探しています。

データベースを見てみましょう。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 55
    }
}
----

それでは、クエリコードを見てみましょう。

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eric"));
List<User> users = mongoTemplate.find(query, User.class);

このロジックは予想どおりに戻ります。

{
    "__id" : ObjectId("55c0e5e5511f0a164a581907"),
    "__class" : "org.baeldung.model.User",
    "name" : "Eric",
    "age" : 45
}

2.2. __正規表現

より柔軟で強力な種類のクエリは正規表現です。このc`はMongoDB $ regex を使用してこのフィールドのこの正規表現に適したすべてのレコードを返す基準を作成します。

これは、 startingWith、endingWith 操作に似ています - 例を見てみましょう。

現在、名前が A で始まるすべてのユーザーを探しています。

これがデータベースの状態です。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581909"),
        "__class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }]----

それでは、クエリを作成しましょう。

Query query = new Query();
query.addCriteria(Criteria.where("name").regex("^A"));
List<User> users = mongoTemplate.find(query,User.class);

これは2つのレコードを実行して返します。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581909"),
        "__class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }]----

これは別の簡単な例です。今回は c で終わる名前を持つすべてのユーザーを探します。

Query query = new Query();
query.addCriteria(Criteria.where("name").regex("c$"));
List<User> users = mongoTemplate.find(query, User.class);

結果は次のようになります。

{
    "__id" : ObjectId("55c0e5e5511f0a164a581907"),
    "__class" : "org.baeldung.model.User",
    "name" : "Eric",
    "age" : 45
}

2.3. Lt gt

これらの演算子は、 $ lt (小なり)演算子および $ gt (大なり)を使用して基準を作成します。

例を簡単に見てみましょう - 私たちは20歳から50歳までのすべてのユーザーを探しています。

データベースは以下のとおりです。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 55
    }
}
----

このクエリコード:

Query query = new Query();
query.addCriteria(Criteria.where("age").lt(50).gt(20));
List<User> users = mongoTemplate.find(query,User.class);

そしてその結果 - 20歳以上50歳未満のすべてのユーザー:

{
    "__id" : ObjectId("55c0e5e5511f0a164a581907"),
    "__class" : "org.baeldung.model.User",
    "name" : "Eric",
    "age" : 45
}

2.4. ソート

Sort は結果のソート順を指定するために使用されます。

次の例では、年齢順に昇順でソートされたすべてのユーザーが返されます。

まず、これが既存のデータです。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581909"),
        "__class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }]----

sort を実行した後:

Query query = new Query();
query.with(new Sort(Sort.Direction.ASC, "age"));
List<User> users = mongoTemplate.find(query,User.class);

そして、これがクエリの結果です - age でうまくソートされています:

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581909"),
        "__class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    }]----

2.5. ページ表示

ページネーションを使用した簡単な例を見てみましょう。

これがデータベースの状態です。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581909"),
        "__class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }]----

さて、クエリロジックは、単にサイズ2のページを要求します。

final Pageable pageableRequest = PageRequest.of(0, 2);
Query query = new Query();
query.with(pageableRequest);

そしてその結果 - 予想どおり2つの文書、

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581907"),
        "__class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    }]----

3生成されたクエリメソッド

Spring Dataが通常提供する、より一般的な種類のクエリ - メソッド名からの自動生成クエリ - を探りましょう。

これらの種類のクエリを利用するために必要な唯一のことは、リポジトリインタフェースでメソッドを宣言することです。

public interface UserRepository
  extends MongoRepository<User, String>, QueryDslPredicateExecutor<User> {
    ...
}

3.1. FindByX

findByタイプのクエリを調べることから始めましょう。この場合は、名前で検索します。

List<User> findByName(String name);

前のセクションと同じ - 2.1 - クエリは同じ結果になり、指定された名前のすべてのユーザーを検索します。

List<User> users = userRepository.findByName("Eric");

3.2. StartingWith および __ endingWith.

__

2.2では、 regex ベースのクエリを調べました。初めと終わりはもちろんそれほど強力ではありませんが、それでも非常に便利です。

これが、操作の概要の簡単な例です。 +

List<User> findByNameStartingWith(String regexp);
List<User> findByNameEndingWith(String regexp);

実際にこれを使用する例は、もちろん非常に簡単です。

List<User> users = userRepository.findByNameStartingWith("A");
List<User> users = userRepository.findByNameEndingWith("c");

そして結果は全く同じです。

3.3. の間に

2.3と同様に、年齢が ageGT から__ageLTまでのすべてのユーザーが返されます。

List<User> findByAgeBetween(int ageGT, int ageLT);

このメソッドを呼び出すと、まったく同じ文書が見つかります。

List<User> users = userRepository.findByAgeBetween(20, 50);

3.4. Like OrderBy

今回はより高度な例を見てみましょう。生成されたクエリに2種類の修飾子を組み合わせたものです。

A という文字を含む名前を持つすべてのユーザーを探します。また、年齢別に結果を昇順で並べます。

List<User> users = userRepository.findByNameLikeOrderByAgeAsc("A");

2.4で使用したデータベースの場合、結果は次のようになります。

----[    {
        "__id" : ObjectId("55c0e5e5511f0a164a581908"),
        "__class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "__id" : ObjectId("55c0e5e5511f0a164a581909"),
        "__class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }]----

4 JSONクエリメソッド

メソッド名や基準を使ってクエリを表現できない場合は、もっと低レベルの何かをすることができます。

このアノテーションで、生のクエリをMongo JSONのクエリ文字列として指定できます。

** 4.1. FindBy

**

単純な方法から始めて、どのように** 検索​​__タイプのメソッドを最初に表すのかを見てみましょう。

@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);

このメソッドはユーザを名前で返す必要があります - プレースホルダ ?0 はメソッドの最初のパラメータを参照します。

List<User> users = userRepository.findUsersByName("Eric");

4.2 $ regex

  • 正規表現駆動型のクエリ** も見てみましょう。もちろん、これは2.2と3.2と同じ結果になります。

@Query("{ 'name' : { $regex: ?0 } }")
List<User> findUsersByRegexpName(String regexp);

使い方もまったく同じです。

List<User> users = userRepository.findUsersByRegexpName("^A");
List<User> users = userRepository.findUsersByRegexpName("c$");

4.3. $ lt $ gt

では、and gt クエリを実装しましょう。

@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")
List<User> findUsersByAgeBetween(int ageGT, int ageLT);

これで、メソッドに2つのパラメータがあるので、生のクエリでは 0 ?1__の各インデックスを参照しています。

List<User> users = userRepository.findUsersByAgeBetween(20, 50);

5 QueryDSLクエリ

MongoRepository はhttp://www.querydsl.com/[QueryDSL]プロジェクトをしっかりサポートしています - そのため、ここでも同様に、型保証された素敵なAPIを活用できます。

** 5.1. Mavenの依存関係

**

まず、pomに定義されているMavenの依存関係が正しいことを確認しましょう。

<dependency>
    <groupId>com.mysema.querydsl</groupId>
    <artifactId>querydsl-mongodb</artifactId>
    <version>3.6.6</version>
</dependency>
<dependency>
    <groupId>com.mysema.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>3.6.6</version>
</dependency>

5.2. Q クラス

QueryDSLはクエリを作成するためにQクラスを使用しました。しかし、実際にはこれらを手作業で作成する必要はないので、** 何らかの方法で生成する必要があります。

そのためにapt-maven-pluginを使います。

<plugin>
    <groupId>com.mysema.maven</groupId>
    <artifactId>apt-maven-plugin</artifactId>
    <version>1.1.3</version>
    <executions>
        <execution>
            <goals>
                <goal>process</goal>
            </goals>
            <configuration>
                <outputDirectory>target/generated-sources/java</outputDirectory>
                <processor>
                  org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
                </processor>
            </configuration>
        </execution>
     </executions>
</plugin>

User クラスを見てみましょう。特に @ QueryEntity アノテーションに注目してください。

@QueryEntity
@Document
public class User {

    @Id
    private String id;
    private String name;
    private Integer age;

   //standard getters and setters
}

Mavenライフサイクルの process 目標(またはその後の別の目標)を実行した後 - aptプラグイン target/generated-sources/java/\ {あなたのパッケージ構造} の下に新しいクラスを 生成します

----/** **
 **  QUser is a Querydsl query type for User
 ** /@Generated("com.mysema.query.codegen.EntitySerializer")
public class QUser extends EntityPathBase<User> {
private static final long serialVersionUID = ...;
public static final QUser user = new QUser("user");
public final NumberPath<Integer> age = createNumber("age", Integer.class);
public final StringPath id = createString("id");
public final StringPath name = createString("name");
public QUser(String variable) {
    super(User.class, forVariable(variable));
}
public QUser(Path<? extends User> path) {
    super(path.getType(), path.getMetadata());
}
    public QUser(PathMetadata<?> metadata) {
        super(User.class, metadata);
    }
}
このクラスの助けを借りて、クエリを作成することはしません。

ちなみに - もしあなたがEclipseを使っているのであれば、このプラグインを導入するとpomで以下のような警告が出るでしょう。

JDKを使用してビルドを実行するか、クラスパスにtools.jarを用意する必要があります。____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________これがeclipseのビルド中に発生する場合は、必ずJDKの下でeclipseを実行してください(com.mysema.maven:apt-maven-plugin:1.1.3:process:デフォルト:generate-sources__

Mavenの__install__は正常に動作し、__QUser__クラスが生成されますが、プラグインがpomでハイライトされています。

手っ取り早い解決策は、__eclipse.ini__で手動でJDKを指定することです。

[source,text,gutter:,true]

…​ -vm {path to jdk}\jdk{your__version}\bin\javaw.exe

====  **  5.3.  __新しいリポジトリ__

**

これで、リポジトリでQueryDSLサポートを実際に有効にする必要があります。これは、__QueryDslPredicateExecutor__インターフェースを単純に** 拡張することによって行われます。

[source,java,gutter:,true]

public interface UserRepository extends MongoRepository<User, String>, QuerydslPredicateExecutor<User>

====  **  5.4.  __Eq__ **

サポートを有効にした状態で、前に説明したものと同じクエリを実装しましょう。

単純な平等から始めましょう。

[source,java,gutter:,true]

QUser qUser = new QUser("user"); Predicate predicate = qUser.name.eq("Eric"); List<User> users = (List<User>) userRepository.findAll(predicate);

====  **  5.5.  __StartingWith__と__EndingWith__ **

同様に、前のクエリを実装しましょう - そして__A__で始まる名前のユーザーを見つけましょう:

[source,java,gutter:,true]

QUser qUser = new QUser("user"); Predicate predicate = qUser.name.startsWith("A"); List<User> users = (List<User>) userRepository.findAll(predicate);

そして__c__で終わる:

[source,java,gutter:,true]

QUser qUser = new QUser("user"); Predicate predicate = qUser.name.endsWith("c"); List<User> users = (List<User>) userRepository.findAll(predicate);

結果は2.2、3.2、または4.2と同じです。

====  **  5.6.  __の間に__**

次の1つのクエリは、20〜50歳の年齢のユーザーを返します。

[source,actionscript3,gutter:,true]

QUser qUser = new QUser("user"); Predicate predicate = qUser.age.between(20, 50); List<User> users = (List<User>) userRepository.findAll(predicate);

===  **  6. 結論**

この記事では、Spring Data MongoDBを使用して照会できるさまざまな方法について説明しました。

一歩後退して、MongoDBにクエリを実行するための強力な方法がいくつあるかを確認するのは興味深いことです。

これらすべての例とコードスニペットの実装は**  https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-data-mongodb[**  GitHubプロジェクト** ]にあります。 Eclipseベースのプロジェクトなので、そのままインポートして実行するのは簡単なはずです。
前の投稿:Javaで配列を初期化する
次の投稿:Javaで配列とコレクションを結合して分割する