Docs Menu
Docs Home
/ /

チュートリアル: String Data を使用したMongoDB のクエリ

このチュートリアルでは、spring Data を使用してMongoDBと連携し、高度なクエリを作成する方法について説明します。 MongoRepositoryインターフェースと MongoTemplateクラスを使用して、データのフィルタリング、アップデート、集計などの操作を実行する方法を学習します。

注意

このチュートリアルでは、spring Data とMongoDBの基本を理解する必要があります。 MongoDBでspring Data を使用する方法の概要については、「 spring Data Framework 統合 」のチュートリアルを参照してください。

Atlas の サンプル データ セット からの映画データを含むコレクションを使用します。

  • spring-data-unlocked 例リポジトリからのソースコード。リポジトリの README の指示に従って、プロジェクトをセットアップして実行します。

  • 無料クラスターを持つMongoDB Atlasアカウント。 Atlas のアカウントとクラスターの作成方法については、 「 MongoDB の使用開始 」ガイドを参照してください。

  • Java 21 以降。

  • Gradle 8.8 以降。

  • ご希望の IDE。

このチュートリアルでは、次の構造を持つトランザクションデータモデルを使用します。

{
"id": "672182814338f60133ee26e1",
"transactionType": "Debit",
"amount": 888.0,
"currency": "USD",
"status": "In Progress",
"description": "Transfer to Ricardo",
"createdAt": "2024-10-09T14:00:00",
"accountDetails": {
"originator": {
"accountNumber": "2376543213",
"name": "Maria",
"bank": "Bank G"
},
"beneficiary": {
"accountNumber": "2234987651",
"name": "Ricardo Mello",
"bank": "Bank V"
}
}
}

このチュートリアルのアプリケーションは、カスタマーレコードとトランザクションを管理するREST APIです。

このチュートリアルでは、次のアクションを実行する方法について説明します。

  • MongoRepository を使用して派生クエリを作成します。

  • @Query アノテーションを使用してクエリを作成します。

  • @Update アノテーションを使用してデータをアップデートします。

  • 集計パイプラインメソッドを確認します。

  • ページネーションを実装します。

  • 柔軟な操作には MongoTemplate を使用します。

1

spring-data-unlockedプロジェクトの src/main/java/com/mongodb/resourcesディレクトリに移動し、TransactionRepository インターフェースを開きます。このインターフェースには、トランザクションをタイプ別に検索するための次のメソッドが含まれています。

List<Transaction> findByTransactionType(String type);

spring Data はメソッド名を使用してクエリを作成します。 findBy プレフィックスはspring Data にクエリを作成するように指示し、TransactionType はフィルタリングするフィールドを指定します。

デバッグ ロギングを有効にするには、application.propertiesファイルに次の行を追加します。

logging.level.org.springframework.data.mongodb=DEBUG

Tip

指定されたプロパティを読み込むには、application.propertiesファイルがクラスパス内にあることを確認してください。

findByTransactionType クエリを実行すると、コンソールに次のような出力が表示されます。

2024-10-15T18:30:33.855-03:00 DEBUG 28992
[SpringShop] [nio-8080-exec-6] o.s.data.mongodb.core.MongoTemplate:
find using query: { "transactionType" : "Transfer"} fields: Document{{}} sort: { "transactionType" : "Transfer"} for class: class com.mongodb.Transaction in collection: transactions

TransactionRepository インターフェースには、金額別にトランザクションを検索し、タイプ別にトランザクションを削除するための次のメソッドも含まれています。

List<Transaction> findByAmountGreaterThan(double amount);
void deleteByTransactionType(String type);
2

TransactionRepository は、@Query アノテーションを使用して statusフィールド値でトランザクションを検索する findByStatus() メソッドを定義します。このメソッドは特定のフィールドのみを返し、結果をソートします。

@Query(
value= "{ 'status' : ?0 }",
fields="{ 'createdAt': 1, 'accountDetails' : 1, 'amount' : 1}",
sort = "{ createdAt: -1}"
)
List<Transaction> findByStatus(String status);

@Query アノテーションのパラメータは以下を指定します。

  • value は、フィルター条件を指定します。

  • fields 結果に含めるフィールドを定義します。

  • sort は、createdAtフィールド値の降順で結果を並べ替えます。

@Queryアノテーションの詳細については、spring Data MongoDB のドキュメントを参照してください。

3

TransactionRepository インターフェースには、トランザクション ステータスを更新するために @Query アノテーションと @Update アノテーションを組み合わせたメソッドが含まれています。

@Query("{ '_id' : ?0 }")
@Update("{ '$set' : { 'status' : ?1 } }")
void updateStatus(String id, String status);

@Query 注釈はIDでドキュメントを検索し、@Update 注釈はステータスフィールドを変更します。

詳しくは、 更新操作 に関するspring Data MongoDB のドキュメントを参照してください。

4

TransactionRepository インターフェースには、@Aggregation アノテーションを使用してトランザクションタイプごとにグループ化された合計金額を計算するメソッドが含まれています。

@Aggregation(pipeline = {
"{ '$match': { 'transactionType': ?0 } }",
"{ '$group': { '_id': '$transactionType', 'amount': { '$sum': '$amount' } } }",
"{ '$project': { 'amount': 1 } }"
})
List<Transaction> getTotalAmountByTransactionType(String transactionType);

この集計パイプラインは、次の操作を実行します。

  • $match トランザクションをタイプ別にフィルタリングします。

  • $group トランザクションをタイプ別にグループ化し、金額を合計します。

  • $project 合計金額を表示。

5

TransactionRepository インターフェースには、$out ステージを使用してエラー トランザクションを新しいコレクションにコピーするメソッドも含まれています。

@Aggregation(pipeline = {
"{ '$match': { 'status': 'error' } }",
"{ '$project': { '_id': 1, 'amount': 1, 'status': 1, 'description': 1, 'createdAt': 1} }",
"{ '$out': 'error_transactions' }"
})
void exportErrorTransactions();

このメソッドを呼び出すと、 MongoDB はerror_transactions という新しいコレクションを作成し、エラー ステータスを持つすべてのドキュメントを挿入します。

重要

このステージを本番環境で使用する前に、 $out 演算子のドキュメントを確認してください。$out ステージは、ターゲットコレクションがすでに存在する場合はそれを置き換えます。

6

src/main/java/com/mongodb/resourcesディレクトリ内の SearchAggregate.javaファイルには、テキスト検索を実行するカスタム注釈を作成する次のコードが含まれています。

import org.springframework.data.mongodb.repository.Aggregation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@Aggregation(pipeline = {
"{ '$search': { 'text': { 'query': ?0, 'path': ?1 } } }"
})
@interface SearchAggregate {
}

TransactionRepository インターフェースには、 アノテーションを使用する次のコードが含まれています。

@SearchAggregate
List<Transaction> search(String query, String path);
7

MongoRepository インターフェースは PagingAndSortingRepository を拡張し、ページ分割をサポートします。 TransactionServiceクラスを開き、次のメソッドを追加します。

public Page<Transaction> findPageableTransactions(
Pageable pageable
) {
return transactionRepository.findAll(pageable);
}

src/main/java/com/mongodb/application/webディレクトリ内の TransactionControllerクラスには、ページ分割パラメータを受け入れる次のコントローラー メソッドが含まれています。

@GetMapping("/pageable")
public PagedModel<Transaction> findAll(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "100") int sizePerPage,
@RequestParam(defaultValue = "ID") String sortField,
@RequestParam(defaultValue = "DESC") Sort.Direction sortDirection) {
Pageable pageable = PageRequest.of(page, sizePerPage, Sort.by(sortDirection, sortField));
return new PagedModel<>(transactionService.findPageableTransactions(pageable));
}

アプリケーションの実行中にターミナルから次のコマンドを実行中て、このエンドポイントを呼び出します。

curl --location 'http://localhost:8080/transactions?page=0&sizePerPage=10&sortField=description&sortDirection=ASC'
8

MongoTemplateクラスは、 MongoDBで操作を実行する際、MongoRepository よりも柔軟性が高くなります。次の手順では、MongoTemplate を使用して一括操作、クエリ、集計を実行する方法を説明します。

src/main/java/com/mongodb/resourcesディレクトリに移動して、MongoConfig.java という名前の構成クラスを表示します。これは MongoTemplate を設定します。

package com.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
@Configuration
public class MongoConfig {
@Bean
public MongoClient mongoClient() {
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString("<your connection string>"))
.build();
return MongoClients.create(settings);
}
@Bean
MongoOperations mongoTemplate(MongoClient mongoClient) {
return new MongoTemplate(mongoClient, "springshop");
}
}
9

src/main/java/com/mongodb/modelディレクトリ内の Customer.javaファイルは、次のレコードを定義します。

package com.mongodb.model;
public record Customer(
String name,
String email,
String accountNumber,
String phone,
Address address
) {
public record Address(
String street,
String city
) {}
}
10

src/main/java/com/mongodb/domain/serviceディレクトリの CustomerServiceクラスには、複数のドキュメントを一度に挿入する次のメソッドが含まれています。

public int bulkCustomerSample(List<Customer> customerList) {
if (findAll().isEmpty()) {
BulkWriteResult result = mongoOperations.bulkOps(BulkOperations.BulkMode.ORDERED, Customer.class)
.insert(customerList)
.execute();
return result.getInsertedCount();
}
return 0;
}

bulkOps メソッドは、すべてのドキュメントをリストに挿入する一括操作を作成します。

11

CustomerServiceクラスには、メールでカスタマーを検索するメソッドが含まれています。

public Customer findCustomerByEmail(String email) {
return mongoOperations.query(Customer.class)
.matching(query(where("email").is(email)))
.one()
.orElseThrow(() -> new RuntimeException("Customer not found with email: " + email));
}

query メソッドは、フィルターを定義する Criteriaオブジェクトを受け入れます。複雑なクエリを作成するには、gt()lt()and()or() などのメソッドを使用できます。

詳細については、 Criteriaクラスのドキュメントを参照してください。

12

src/main/java/com/mongodb/domain/modelディレクトリ内の CustomersByCityクラスには、集計結果を保持する次のレコードが含まれています。

public record CustomersByCity(
String id,
int total
){}

CustomerService.javaファイルには、顧客を都市別にカウントするメソッドが含まれています。

public List<CustomersByCity> totalCustomerByCity() {
TypedAggregation<Customer> aggregation = newAggregation(Customer.class,
group("address.city")
.count().as("total"),
Aggregation.sort(Sort.Direction.ASC, "_id"),
project(Fields.fields("total", "_id")));
AggregationResults<CustomersByCity> result = mongoOperations.aggregate(aggregation, CustomersByCity.class);
return result.getMappedResults();
}

このメソッドは、カスタマーを都市別にグループ化し、各都市のカスタマー数をカウントします。

13

アプリケーションを実行するには、IDE で SpringShopApplicationクラスを実行中か、ターミナルから次のコマンドを実行中。

export MONGODB_URI="<YOUR_CONNECTION_STRING>"
./gradlew bootRun

アプリケーションはポート 8080 で実行されます。前の手順で定義されたエンドポイントに リクエストを送信して、クエリをテストできます。

このアプリケーションのエンドポイントをテストする方法の詳細については、spring-data-unlockedリポジトリの README を参照してください。

spring Data MongoDBの詳細については、spring Data MongoDB のドキュメントを参照してください。

集計パイプラインの詳細については、 MongoDB Serverマニュアルの「 集計 」を参照してください。

戻る

Spring Data MongoDB