1. Přehled
Při používání Spring Data MongoDB možná budeme muset omezit vlastnosti mapované z databázového objektu. Obvykle to můžeme potřebovat například z bezpečnostních důvodů – abychom se vyhnuli odhalení citlivých informací uložených na serveru. Nebo také můžeme například potřebovat odfiltrovat část dat zobrazených ve webové aplikaci.
V tomto krátkém tutoriálu uvidíme, jak MongoDB aplikuje omezení pole.
2. Omezení polí MongoDB pomocí projekce
MongoDB používá projekci k určení nebo omezení polí, která se mají vrátit z dotazu . Pokud však používáme jarní data, chceme je použít s MongoTemplate nebo MongoRepository .
Proto chceme vytvořit testovací případy pro obě MongoTemplate a MongoRepository kde můžeme aplikovat omezení pole.
3. Implementace projekce
3.1. Nastavení entity
Nejprve vytvořte Inventář třída:
@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. Nastavení úložiště
Poté otestujte MongoRepository , vytvoříme InventoryRepository . Použijeme také kde stav s @Query . Například chceme filtrovat stav zásob:
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. Přidání závislostí Maven
Budeme také používat Embedded MongoDB. Přidáme spring-data-mongodb a de.flapdoodle.embed.mongo závislosti na našem pom.xml soubor:
<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. Otestujte pomocí MongoRepository a MongoTemplate
Pro MongoRepository , uvidíme příklady pomocí @Query a použití omezení polí, zatímco pro MongoTemplate , použijeme Dotaz třída.
Pokusíme se pokrýt všechny různé kombinace zahrnutí a vyloučení. Zejména uvidíme, jak omezit vložená pole nebo, což je zajímavější, pole pomocí slice vlastnictví .
Ke každému testu přidáme MongoRepository nejprve příklad, následovaný vzorem MongoTemplate .
4.1. Zahrnout pouze pole
Začněme zahrnutím některých polí. Všechny vyloučené budou mít null . Projekce přidá _id ve výchozím nastavení:
List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusFields("A");
inventoryList.forEach(i -> {
assertNotNull(i.getId());
assertNotNull(i.getItem());
assertNotNull(i.getStatus());
assertNull(i.getSize());
assertNull(i.getInStock());
});
Nyní se podívejme na MongoTemplate verze:
Query query = new Query();
query.fields()
.include("item")
.include("status");
4.2. Zahrnout a vyloučit pole
Tentokrát uvidíme příklady, které explicitně zahrnují některá pole, ale vylučují jiná – v tomto případě vyloučíme _id pole:
List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusExcludeIdFields("A");
inventoryList.forEach(i -> {
assertNotNull(i.getItem());
assertNotNull(i.getStatus());
assertNull(i.getId());
assertNull(i.getSize());
assertNull(i.getInStock());
});
Ekvivalentní dotaz pomocí MongoTemplate by bylo:
Query query = new Query();
query.fields()
.include("item")
.include("status")
.exclude("_id");
4.3. Pouze Vyloučit pole
Pokračujme vyloučením některých polí. Všechna ostatní pole nebudou mít hodnotu 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());
});
A pojďme se podívat na MongoTemplate verze:
Query query = new Query();
query.fields()
.exclude("status")
.exclude("inStock");
4.4. Zahrnout vložená pole
Opět platí, že včetně vložených polí je přidá do našeho výsledku:
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());
});
Podívejme se, jak udělat totéž s MongoTemplate :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.include("size.uom");
4.5. Vyloučit vložená pole
Stejně tak vyloučení vložených polí je zabrání v našem výsledku, přidá se však zbytek vložených polí :
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());
});
Pojďme se podívat na MongoTemplate verze:
Query query = new Query();
query.fields()
.exclude("size.uom");
4.6. Zahrnout vložená pole do pole
Podobně jako u jiných polí můžeme také přidat projekci pole pole:
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());
});
Implementujeme totéž pomocí MongoTemplate :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.include("inStock.quantity");
4.7. Zahrnout vložená pole do pole pomocí slice
MongoDB může pomocí funkcí JavaScriptu omezit výsledky pole – například získat pouze poslední prvek v poli pomocí 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());
});
Proveďme stejný dotaz pomocí MongoTemplate :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.slice("inStock", -1);