sql >> Databáze >  >> NoSQL >> MongoDB

Vrátit pouze konkrétní pole pro dotaz v Spring Data MongoDB

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

  1. příkaz mongo nebyl rozpoznán při pokusu o připojení k serveru mongodb

  2. Tipy pro správu zálohování MongoDB pro sdílené clustery

  3. Vytvářejte, čtěte, aktualizujte, mažte data pomocí Node.js - Mongoose

  4. Definování schématu Mongoose za běhu z „popisu“ ve formátu JSON