sql >> Database >  >> NoSQL >> MongoDB

Retourneer alleen specifieke velden voor een query in Spring Data MongoDB

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

  1. Hoe maak je een failover naar een nieuw hoofdknooppunt bij gebruik van Redis met Sentinel en redis-py?

  2. dus je HBase is kapot

  3. Een reeds uitgevoerde taak annuleren in Python RQ?

  4. Hoe voeg je een json toe aan een geneste array van een mongodb-document met Spring?