1. Übersicht
Bei der Verwendung von Spring Data MongoDB müssen wir möglicherweise die von einem Datenbankobjekt zugeordneten Eigenschaften einschränken. Typischerweise benötigen wir dies beispielsweise aus Sicherheitsgründen – um zu vermeiden, dass auf einem Server gespeicherte sensible Informationen preisgegeben werden. Oder wir müssen beispielsweise einen Teil der in einer Webanwendung angezeigten Daten herausfiltern.
In diesem kurzen Tutorial werden wir sehen, wie MongoDB Feldbeschränkungen anwendet.
2. Einschränkung von MongoDB-Feldern durch Projektion
MongoDB verwendet Projection, um Felder anzugeben oder einzuschränken, die von einer Abfrage zurückgegeben werden sollen . Wenn wir jedoch Spring Data verwenden, möchten wir dies mit MongoTemplate anwenden oder MongoRepository .
Daher wollen wir Testfälle für beide MongoTemplate erstellen und MongoRepository wo wir Feldbeschränkungen anwenden können.
3. Projektion implementieren
3.1. Einrichtung der Entität
Lassen Sie uns zuerst ein Inventar erstellen 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. Repository einrichten
Dann zum Testen von MongoRepository erstellen wir ein InventoryRepository . Wir verwenden auch ein where Bedingung mit @Query . Wir möchten beispielsweise nach dem Bestandsstatus filtern:
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. Hinzufügen der Maven-Abhängigkeiten
Wir werden auch Embedded MongoDB verwenden. Lassen Sie uns die spring-data-mongodb hinzufügen und de.flapdoodle.embed.mongo Abhängigkeiten zu unserer pom.xml Datei:
<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. Testen Sie mit MongoRepository und MongoTemplate
Für MongoRepository , sehen wir Beispiele mit @Query und Feldbeschränkung anwenden, während für MongoTemplate , verwenden wir die Abfrage Klasse.
Wir werden versuchen, alle verschiedenen Kombinationen von Einschließen und Ausschließen abzudecken. Insbesondere werden wir sehen, wie man eingebettete Felder oder, interessanter, Arrays mit dem Slice einschränkt Eigentum .
Für jeden Test fügen wir das MongoRepository hinzu Beispiel zuerst, gefolgt von dem für MongoTemplate .
4.1. Nur Felder einschließen
Beginnen wir damit, einige Felder einzuschließen. Alle ausgeschlossenen sind null . Die Projektion fügt die _id hinzu standardmäßig:
List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusFields("A");
inventoryList.forEach(i -> {
assertNotNull(i.getId());
assertNotNull(i.getItem());
assertNotNull(i.getStatus());
assertNull(i.getSize());
assertNull(i.getInStock());
});
Schauen wir uns nun das MongoTemplate an Version:
Query query = new Query();
query.fields()
.include("item")
.include("status");
4.2. Felder einschließen und ausschließen
Dieses Mal sehen wir Beispiele, die einige Felder ausdrücklich einschließen, andere jedoch ausschließen – in diesem Fall schließen wir die _id aus Feld:
List<Inventory> inventoryList = inventoryRepository.findByStatusIncludeItemAndStatusExcludeIdFields("A");
inventoryList.forEach(i -> {
assertNotNull(i.getItem());
assertNotNull(i.getStatus());
assertNull(i.getId());
assertNull(i.getSize());
assertNull(i.getInStock());
});
Die entsprechende Abfrage mit MongoTemplate wäre:
Query query = new Query();
query.fields()
.include("item")
.include("status")
.exclude("_id");
4.3. Nur Felder ausschließen
Fahren wir fort, indem wir einige Felder ausschließen. Alle anderen Felder sind nicht 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());
});
Und schauen wir uns das MongoTemplate an Version:
Query query = new Query();
query.fields()
.exclude("status")
.exclude("inStock");
4.4. Eingebettete Felder einschließen
Auch hier werden sie durch das Einbeziehen eingebetteter Felder zu unserem Ergebnis hinzugefügt:
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());
});
Sehen wir uns an, wie man dasselbe mit MongoTemplate macht :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.include("size.uom");
4.5. Eingebettete Felder ausschließen
Das Ausschließen eingebetteter Felder hält sie ebenfalls aus unserem Ergebnis heraus, würde jedoch den Rest der eingebetteten Felder hinzufügen :
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());
});
Werfen wir einen Blick auf das MongoTemplate Version:
Query query = new Query();
query.fields()
.exclude("size.uom");
4.6. Eingebettete Felder in Array einschließen
Ähnlich wie bei anderen Feldern können wir auch eine Projektion des Feldes eines Arrays hinzufügen:
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());
});
Lassen Sie uns dasselbe mit MongoTemplate implementieren :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.include("inStock.quantity");
4.7. Eingebettete Felder mit slice in das Array einschließen
MongoDB kann JavaScript-Funktionen verwenden, um die Ergebnisse eines Arrays zu begrenzen – zum Beispiel, indem mit slice nur das letzte Element in einem Array abgerufen wird :
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());
});
Führen wir dieselbe Abfrage mit MongoTemplate durch :
Query query = new Query();
query.fields()
.include("item")
.include("status")
.slice("inStock", -1);