sql >> Databasteknik >  >> NoSQL >> MongoDB

Returnera endast specifika fält för en fråga i Spring Data MongoDB

1. Översikt

När du använder Spring Data MongoDB kan vi behöva begränsa egenskaperna som mappas från ett databasobjekt. Vanligtvis kan vi behöva detta, till exempel av säkerhetsskäl – för att undvika att exponera känslig information som lagras på en server. Eller också, till exempel, kan vi behöva filtrera bort en del av data som visas i en webbapplikation.

I den här korta handledningen kommer vi att se hur MongoDB tillämpar fältbegränsningar.

2. MongoDB-fältbegränsning med hjälp av projektion

MongoDB använder Projection för att specificera eller begränsa fält som ska returneras från en fråga . Men om vi använder Spring Data vill vi tillämpa detta med MongoTemplate eller MongoRepository .

Därför vill vi skapa testfall för båda MongoTemplate och MongoRepository där vi kan tillämpa fältbegränsningar.

3. Implementera projektion

3.1. Konfigurera enheten

Låt oss först skapa ett Inventarium klass:

@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. Konfigurera arkivet

För att sedan testa MongoRepository skapar vi ett InventoryRepository . Vi använder också en var skick med @Query . Vi vill till exempel filtrera 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. Lägga till Maven Dependencies

Vi kommer också att använda Embedded MongoDB. Låt oss lägga till spring-data-mongodb och de.flapdoodle.embed.mongo beroenden till vår 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. Testa med MongoRepository och MongoTemplate

För MongoRepository , kommer vi att se exempel med @Query och tillämpa fältbegränsning, medan för MongoTemplate , kommer vi att använda  Fråga  klass.

Vi kommer att försöka täcka alla olika kombinationer av inkludera och exkludera. Särskilt kommer vi att se hur man begränsar inbäddade fält eller, mer intressant, arrayer med segmentet egendom .

För varje test lägger vi till MongoRepository exemplet först, följt av det för MongoTemplate .

4.1. Inkludera endast fält

Låt oss börja med att inkludera några fält. Alla uteslutna kommer att vara null . Projektionen lägger till _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());
});

Nu ska vi kolla in MongoTemplate version:

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

4.2. Inkludera och exkludera fält

Den här gången kommer vi att se exempel som uttryckligen inkluderar vissa fält men utesluter andra – i det här fallet kommer vi att utesluta _id fält:

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

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

Motsvarande fråga med MongoTemplate skulle vara:

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

4.3. Exkludera endast fält

Låt oss fortsätta med att utesluta några fält. Alla andra fält kommer att vara icke-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());
});

Och låt oss kolla in MongoTemplate version:

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

4.4. Inkludera inbäddade fält

Återigen, inklusive inbäddade fält kommer att lägga till dem till vårt 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());
});

Låt oss se hur du gör samma sak med MongoTemplate :

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

4.5. Uteslut inbäddade fält

På samma sätt, att utesluta inbäddade fält håller dem borta från vårt resultat, men det skulle lägga till resten av de inbäddade fälten :

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

Låt oss ta en titt på MongoTemplate version:

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

4.6. Inkludera inbäddade fält i Array

På samma sätt som andra fält kan vi också lägga till en projektion av en arrays fält:

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

Låt oss implementera samma sak med MongoTemplate :

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

4.7. Inkludera inbäddade fält i Array med slice

MongoDB kan använda JavaScript-funktioner för att begränsa resultaten av en array – till exempel att bara få det sista elementet i en array med 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());
});

Låt oss utföra samma fråga med MongoTemplate :

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

  1. finns det ett sätt att automatiskt generera ObjectId när en mongoose Model är ny?

  2. Redis - Befordra en slav till master manuellt

  3. Mongodb summerar storleken på arrayfält

  4. MongoDB Ersätt specifika matrisvärden