sql >> Database teknologi >  >> NoSQL >> MongoDB

Returner kun specifikke felter for en forespørgsel i Spring Data MongoDB

1. Oversigt

Når du bruger Spring Data MongoDB, skal vi muligvis begrænse de egenskaber, der er kortlagt fra et databaseobjekt. Typisk kan vi have brug for dette, for eksempel af sikkerhedsmæssige årsager – for at undgå at afsløre følsomme oplysninger gemt på en server. Eller også kan vi for eksempel være nødt til at bortfiltrere en del af de data, der vises i en webapplikation.

I denne korte øvelse vil vi se, hvordan MongoDB anvender feltbegrænsning.

2. MongoDB-feltbegrænsning ved hjælp af projektion

MongoDB bruger Projection til at specificere eller begrænse felter, der skal returneres fra en forespørgsel . Men hvis vi bruger Spring Data, ønsker vi at anvende dette med MongoTemplate eller MongoRepository .

Derfor ønsker vi at oprette testcases for begge MongoTemplate og MongoRepository hvor vi kan anvende feltrestriktioner.

3. Implementering af projektion

3.1. Opsætning af entiteten

Lad os først oprette en Beholdning klasse:

@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. Opsætning af repository

Derefter for at teste MongoRepository , opretter vi et InventoryRepository . Vi bruger også et hvor tilstand med @Query . For eksempel ønsker vi at filtrere efter lagerstatus:

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. Tilføjelse af Maven-afhængighederne

Vi bruger også Embedded MongoDB. Lad os tilføje spring-data-mongodb og de.flapdoodle.embed.mongo afhængigheder til vores pom.xml fil:

<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. Test med MongoRepository og MongoTemplate

Til MongoRepository , vil vi se eksempler, der bruger @Query og anvendelse af feltbegrænsning, mens for MongoTemplate , bruger vi  Forespørgsel  klasse.

Vi vil forsøge at dække alle forskellige kombinationer af inkludere og ekskludere. Vi vil især se, hvordan man begrænser indlejrede felter eller, mere interessant, arrays ved hjælp af udsnittet ejendom .

For hver test tilføjer vi MongoRepository eksemplet først, efterfulgt af det for MongoTemplate .

4.1. Inkluder kun felter

Lad os starte med at inkludere nogle felter. Alle ekskluderede vil være null . Projektionen tilføjer _id som standard:

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

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

Lad os nu tjekke MongoTemplate version:

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

4.2. Inkluder og ekskluder felter

Denne gang vil vi se eksempler, der eksplicit inkluderer nogle felter, men udelukker andre – i dette tilfælde vil vi ekskludere _id felt:

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

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

Den tilsvarende forespørgsel ved hjælp af MongoTemplate ville være:

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

4.3. Ekskluder kun felter

Lad os fortsætte med at ekskludere nogle felter. Alle andre felter er ikke-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());
});

Og lad os se MongoTemplate version:

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

4.4. Inkluder indlejrede felter

Igen, herunder indlejrede felter vil tilføje dem til vores resultat:

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());
});

Lad os se, hvordan du gør det samme med MongoTemplate :

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

4.5. Ekskluder indlejrede felter

Ligeledes udelukker du indlejrede felter, så holdes de ude af vores resultat, men det ville tilføje resten af ​​de indlejrede felter :

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());
});

Lad os tage et kig på MongoTemplate version:

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

4.6. Inkluder indlejrede felter i Array

På samme måde som andre felter kan vi også tilføje en projektion af et arrays felt:

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());
});

Lad os implementere det samme ved hjælp af MongoTemplate :

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

4.7. Inkluder indlejrede felter i Array ved hjælp af slice

MongoDB kan bruge JavaScript-funktioner til at begrænse resultaterne af et array – for eksempel ved kun at få det sidste element i et array ved hjælp af slice :

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());
});

Lad os udføre den samme forespørgsel ved hjælp af MongoTemplate :

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

  1. MongoDB:Hvordan definerer man et skema?

  2. MongoDB forbinder data inde i en række objekter

  3. Mongodb opdatering dybt indlejret underdokument

  4. Håndtering af Mongoose-valideringsfejl – hvor og hvordan?