1. 概要

Spring Data MongoDB を使用する場合、データベースオブジェクトからマップされるプロパティを制限する必要がある場合があります。 通常、これは、たとえばセキュリティ上の理由から、サーバーに保存されている機密情報の公開を回避するために必要になる場合があります。 または、たとえば、Webアプリケーションに表示されるデータの一部を除外する必要がある場合もあります。

この短いチュートリアルでは、MongoDBがフィールド制限をどのように適用するかを見ていきます。

2. 射影を使用したMongoDBフィールドの制限

MongoDBは、Projectionを使用して、クエリから返すフィールドを指定または制限します。 ただし、Spring Dataを使用している場合は、これをMongoTemplateまたはMongoRepositoryで適用します。

したがって、フィールド制限を適用できるMongoTemplateMongoRepositoryの両方のテストケースを作成する必要があります。

3. プロジェクションの実装

3.1. エンティティの設定

まず、Inventoryクラスを作成しましょう。

@Document(collection = "inventory")
public class Inventory {

    @Id
    private String id;
    private String status;
    private Size size;
    private InStock inStock;

    // standard getters and setters    
}

3.2. リポジトリの設定

次に、 MongoRepository をテストするために、InventoryRepositoryを作成します。 また、@Querywhere条件を使用します。 たとえば、在庫ステータスをフィルタリングする必要があります。

public interface InventoryRepository extends MongoRepository<Inventory, String> {

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'item' : 1, 'status' : 1 }")
    List<Inventory> findByStatusIncludeItemAndStatusFields(String status);

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'item' : 1, 'status' : 1, '_id' : 0 }")
    List<Inventory> findByStatusIncludeItemAndStatusExcludeIdFields(String status);

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'status' : 0, 'inStock' : 0 }")
    List<Inventory> findByStatusIncludeAllButStatusAndStockFields(String status);

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'item' : 1, 'status' : 1, 'size.uom': 1 }")
    List<Inventory> findByStatusIncludeEmbeddedFields(String status);

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'size.uom': 0 }")
    List<Inventory> findByStatusExcludeEmbeddedFields(String status);

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'item' : 1, 'status' : 1, 'inStock.quantity': 1 }")
    List<Inventory> findByStatusIncludeEmbeddedFieldsInArray(String status);

    @Query(value = "{ 'status' : ?0 }", fields = "{ 'item' : 1, 'status' : 1, 'inStock': { $slice: -1 } }")
    List<Inventory> findByStatusIncludeEmbeddedFieldsLastElementInArray(String status);

}

3.3. Mavenの依存関係の追加

EmbeddedMongoDBも使用します。L pom.xmlファイルにspring-data-mongodbとde.flapdoodle.embed.mongoの依存関係を追加しましょう

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>3.0.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <version>3.2.6</version>
    <scope>test</scope>
</dependency>

4. MongoRepositoryおよびMongoTemplateを使用してテストします

MongoRepository の場合、@Queryを使用してフィールド制限を適用した例を示します。 MongoTemplate には、を使用しますクエリ クラス。

インクルードとエクスクルードのさまざまな組み合わせをすべてカバーするようにします。 特に、sliceプロパティを使用して、埋め込みフィールドまたはさらに興味深いことに配列を制限する方法を説明します。

テストごとに、 MongoRepository 最初の例、次に MongoTemplate.

4.1. フィールドのみを含める

いくつかのフィールドを含めることから始めましょう。 除外されるものはすべてnullになります。 投影は_を追加しますid デフォルト:

List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusFields("A");

inventoryList.forEach(i -> {
  assertNotNull(i.getId());
  assertNotNull(i.getItem());
  assertNotNull(i.getStatus());
  assertNull(i.getSize());
  assertNull(i.getInStock());
});

それでは、MongoTemplateバージョンを確認してみましょう。

Query query = new Query();
 query.fields()
   .include("item")
   .include("status");

4.2. フィールドの包含と除外

今回は、一部のフィールドを明示的に含み、他のフィールドを除外する例を示します。この場合、_ idフィールドを除外します。

List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusExcludeIdFields("A");

inventoryList.forEach(i -> {
   assertNotNull(i.getItem());
   assertNotNull(i.getStatus());
   assertNull(i.getId());
   assertNull(i.getSize());
   assertNull(i.getInStock());
});

MongoTemplateを使用した同等のクエリは次のようになります。

Query query = new Query();
query.fields()
  .include("item")
  .include("status")
  .exclude("_id");

4.3. フィールドのみを除外する

いくつかのフィールドを除外して続行しましょう。 他のすべてのフィールドはnull以外になります。

List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeAllButStatusAndStockFields("A");

inventoryList.forEach(i -> {
  assertNotNull(i.getItem());
  assertNotNull(i.getId());
  assertNotNull(i.getSize());
  assertNull(i.getInStock());
  assertNull(i.getStatus());
});

そして、MongoTemplateバージョンをチェックしてみましょう。

Query query = new Query();
query.fields()
  .exclude("status")
  .exclude("inStock");

4.4. 埋め込みフィールドを含める

繰り返しますが、埋め込みフィールドを含めると、結果に追加されます。

List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeEmbeddedFields("A");

inventoryList.forEach(i -> {
  assertNotNull(i.getItem());
  assertNotNull(i.getStatus());
  assertNotNull(i.getId());
  assertNotNull(i.getSize());
  assertNotNull(i.getSize().getUom());
  assertNull(i.getSize().getHeight());
  assertNull(i.getSize().getWidth());
  assertNull(i.getInStock());
});

MongoTemplateで同じことを行う方法を見てみましょう。

Query query = new Query();
query.fields()
  .include("item")
  .include("status")
  .include("size.uom");

4.5. 埋め込みフィールドを除外する

同様に、埋め込みフィールドを除外すると、結果から除外されますが、残りの埋め込みフィールドが追加されます。

List<Inventory> inventoryList = inventoryRepository.findByStatusExcludeEmbeddedFields("A");

inventoryList.forEach(i -> {
  assertNotNull(i.getItem());
  assertNotNull(i.getStatus());
  assertNotNull(i.getId());
  assertNotNull(i.getSize());
  assertNull(i.getSize().getUom());
  assertNotNull(i.getSize().getHeight());
  assertNotNull(i.getSize().getWidth());
  assertNotNull(i.getInStock());
});

MongoTemplateバージョンを見てみましょう。

Query query = new Query();
query.fields()
  .exclude("size.uom");

4.6. 埋め込みフィールドを配列に含める

他のフィールドと同様に、配列のフィールドの射影を追加することもできます。

List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeEmbeddedFieldsInArray("A");

inventoryList.forEach(i -> {
  assertNotNull(i.getItem());
  assertNotNull(i.getStatus());
  assertNotNull(i.getId());
  assertNotNull(i.getInStock());
  i.getInStock()
    .forEach(stock -> {
      assertNull(stock.getWareHouse());
      assertNotNull(stock.getQuantity());
     });
  assertNull(i.getSize());
});

MongoTemplateを使用して同じものを実装しましょう。

Query query = new Query();
query.fields()
  .include("item")
  .include("status")
  .include("inStock.quantity");

4.7. スライスを使用して配列に埋め込みフィールドを含める

MongoDBは、JavaScript関数を使用して配列の結果を制限できます。たとえば、スライスを使用して配列の最後の要素のみを取得します。

List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeEmbeddedFieldsLastElementInArray("A");

inventoryList.forEach(i -> {
  assertNotNull(i.getItem());
  assertNotNull(i.getStatus());
  assertNotNull(i.getId());
  assertNotNull(i.getInStock());
  assertEquals(1, i.getInStock().size());
  assertNull(i.getSize());
});

MongoTemplateを使用して同じクエリを実行してみましょう。

Query query = new Query();
query.fields()
  .include("item")
  .include("status")
  .slice("inStock", -1);

5. 結論

この記事では、SpringDataMongoDBの予測について説明しました。

fields MongoRepositoryインターフェースと@Queryの両方で使用した例を見てきました アノテーション、および MongoTemplateおよびQueryクラス。

いつものように、これらの例のコードはGitHubから入手できます。