1. Overzicht
Wanneer we Spring Data MongoDB gebruiken, moeten we mogelijk de eigenschappen beperken die zijn toegewezen aan een databaseobject. Meestal hebben we dit bijvoorbeeld nodig om veiligheidsredenen - om te voorkomen dat gevoelige informatie die op een server is opgeslagen, wordt vrijgegeven. Of het kan ook zijn dat we bijvoorbeeld een deel van de gegevens moeten uitfilteren die in een webapplicatie worden weergegeven.
In deze korte tutorial zullen we zien hoe MongoDB veldbeperking toepast.
2. MongoDB-veldbeperking met projectie
MongoDB gebruikt Projection om velden te specificeren of te beperken die moeten worden geretourneerd uit een query . Als we echter Spring Data gebruiken, willen we dit toepassen met MongoTemplate of MongoRepository .
Daarom willen we testcases maken voor zowel MongoTemplate en MongoRepository waar we veldbeperkingen kunnen toepassen.
3. Projectie implementeren
3.1. De entiteit instellen
Laten we eerst een inventaris maken klas:
@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. De opslagplaats instellen
Om vervolgens MongoRepository te testen , we maken een InventoryRepository . We gebruiken ook een waar voorwaarde met @Query . We willen bijvoorbeeld filteren op de voorraadstatus:
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. De Maven-afhankelijkheden toevoegen
We zullen ook Embedded MongoDB gebruiken. Laten we de spring-data-mongodb . toevoegen en de.flapdoodle.embed.mongo afhankelijkheden van onze pom.xml bestand:
<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 met MongoRepository en MongoTemplate
Voor MongoRepository , we zullen voorbeelden zien met @Query en het toepassen van veldbeperking, while voor MongoTemplate , we gebruiken de Query klas.
We zullen proberen alle verschillende combinaties van opnemen en uitsluiten te behandelen. We zullen in het bijzonder zien hoe we ingesloten velden of, interessanter, arrays kunnen beperken met behulp van de slice eigendom .
Voor elke test voegen we de MongoRepository . toe voorbeeld eerst, gevolgd door die voor MongoTemplate .
4.1. Alleen velden opnemen
Laten we beginnen met het opnemen van enkele velden. Alle uitgesloten zijn null . De projectie voegt de _id . toe standaard:
List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusFields("A");
inventoryList.forEach(i -> {
assertNotNull(i.getId());
assertNotNull(i.getItem());
assertNotNull(i.getStatus());
assertNull(i.getSize());
assertNull(i.getInStock());
});
Laten we nu eens kijken naar de MongoTemplate versie:
Query query = new Query();
query.fields()
.include("item")
.include("status");
4.2. Velden opnemen en uitsluiten
Deze keer zullen we voorbeelden zien die expliciet sommige velden bevatten, maar andere uitsluiten - in dit geval zullen we de _id uitsluiten veld:
List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusExcludeIdFields("A");
inventoryList.forEach(i -> {
assertNotNull(i.getItem());
assertNotNull(i.getStatus());
assertNull(i.getId());
assertNull(i.getSize());
assertNull(i.getInStock());
});
De equivalente zoekopdracht met MongoTemplate zou zijn:
Query query = new Query();
query.fields()
.include("item")
.include("status")
.exclude("_id");
4.3. Alleen velden uitsluiten
Laten we doorgaan door enkele velden uit te sluiten. Alle andere velden zijn niet-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());
});
En laten we eens kijken naar de MongoTemplate versie:
Query query = new Query();
query.fields()
.exclude("status")
.exclude("inStock");
4.4. Ingesloten velden opnemen
Nogmaals, het opnemen van ingesloten velden zal ze aan ons resultaat toevoegen:
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());
});
Laten we eens kijken hoe we hetzelfde kunnen doen met MongoTemplate :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.include("size.uom");
4.5. Ingesloten velden uitsluiten
Evenzo houdt exclusief ingesloten velden ze buiten ons resultaat, maar het zou de rest van de ingesloten velden toevoegen :
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());
});
Laten we eens kijken naar de MongoTemplate versie:
Query query = new Query();
query.fields()
.exclude("size.uom");
4.6. Ingesloten velden in matrix opnemen
Net als bij andere velden kunnen we ook een projectie van het veld van een array toevoegen:
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());
});
Laten we hetzelfde implementeren met MongoTemplate :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.include("inStock.quantity");
4.7. Ingesloten velden in matrix opnemen met slice
MongoDB kan JavaScript-functies gebruiken om de resultaten van een array te beperken, bijvoorbeeld door alleen het laatste element in een array te krijgen met behulp van 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());
});
Laten we dezelfde zoekopdracht uitvoeren met MongoTemplate :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.slice("inStock", -1);