MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Kembalikan Hanya Bidang Tertentu untuk Kueri di Spring Data MongoDB

1. Ikhtisar

Saat menggunakan Spring Data MongoDB, kami mungkin perlu membatasi properti yang dipetakan dari objek database. Biasanya, kami mungkin memerlukan ini, misalnya, untuk alasan keamanan – untuk menghindari pengungkapan informasi sensitif yang disimpan di server. Atau juga, misalnya, kita mungkin perlu memfilter sebagian data yang ditampilkan dalam aplikasi web.

Dalam tutorial singkat ini, kita akan melihat bagaimana MongoDB menerapkan pembatasan bidang.

2. Batasan Bidang MongoDB Menggunakan Proyeksi

MongoDB menggunakan Proyeksi untuk menentukan atau membatasi bidang yang akan dikembalikan dari kueri . Namun, jika kita menggunakan Spring Data, kita ingin menerapkannya dengan MongoTemplate atau MongoRepository .

Oleh karena itu, kami ingin membuat kasus pengujian untuk keduanya MongoTemplate dan MongoRepository tempat kami dapat menerapkan batasan bidang.

3. Menerapkan Proyeksi

3.1. Menyiapkan Entitas

Pertama, mari buat Inventaris kelas:

@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. Menyiapkan Repositori

Kemudian, untuk menguji MongoRepository , kami membuat InventoryRepository . Kami juga akan menggunakan di mana kondisi dengan @Query . Misalnya, kami ingin memfilter status inventaris:

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. Menambahkan Dependensi Maven

Kami juga akan menggunakan MongoDB Tersemat. Mari tambahkan spring-data-mongodb dan de.flapdoodle.embed.mongo dependensi ke pom.xml our kami berkas:

<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. Uji Menggunakan MongoRepository dan MongoTemplate

Untuk MongoRepository , kita akan melihat contoh menggunakan @Query dan menerapkan Pembatasan Bidang, sedangkan untuk MongoTemplate , kami akan menggunakan  Kueri  kelas.

Kami akan mencoba untuk mencakup semua kombinasi yang berbeda termasuk dan kecualikan. Khususnya, kita akan melihat cara membatasi bidang yang disematkan atau, yang lebih menarik, larik menggunakan slice properti .

Untuk setiap pengujian, kami akan menambahkan MongoRepository contoh pertama, diikuti oleh satu untuk MongoTemplate .

4.1. Hanya Sertakan Kolom

Mari kita mulai dengan memasukkan beberapa bidang. Semua yang dikecualikan akan menjadi null . Proyeksi menambahkan _id secara default:

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

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

Sekarang, mari kita periksa MongoTemplate versi:

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

4.2. Sertakan dan Kecualikan Bidang

Kali ini, kita akan melihat contoh yang secara eksplisit menyertakan beberapa bidang tetapi mengecualikan yang lain – dalam hal ini, kami akan mengecualikan _id bidang:

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

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

Kueri yang setara menggunakan MongoTemplate akan menjadi:

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

4.3. Hanya Kecualikan Bidang

Mari kita lanjutkan dengan mengecualikan beberapa bidang. Semua bidang lainnya tidak akan nol:

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

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

Dan, mari kita periksa MongoTemplate versi:

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

4.4. Sertakan Bidang Tersemat

Sekali lagi, menyertakan bidang yang disematkan akan menambahkannya ke hasil kami:

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

Mari kita lihat bagaimana melakukan hal yang sama dengan MongoTemplate :

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

4.5. Kecualikan Bidang Tersemat

Demikian juga, mengecualikan bidang yang disematkan membuat mereka keluar dari hasil kami, namun, itu akan menambahkan sisa bidang yang disematkan :

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

Mari kita lihat MongoTemplate versi:

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

4.6. Sertakan Bidang Tersemat dalam Array

Sama halnya dengan bidang lain, kami juga dapat menambahkan proyeksi bidang array:

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

Mari kita terapkan hal yang sama menggunakan MongoTemplate :

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

4.7. Sertakan Bidang Tersemat dalam Array menggunakan slice

MongoDB dapat menggunakan fungsi JavaScript untuk membatasi hasil larik – misalnya, hanya mendapatkan elemen terakhir dalam larik menggunakan 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());
});

Mari lakukan kueri yang sama menggunakan MongoTemplate :

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

  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. BadValue Tidak valid atau tidak ada set lokal pengguna. Harap pastikan variabel lingkungan LANG dan/atau LC_* disetel dengan benar

  2. Objek Dokumen MongoEngine yang dibuat menggunakan from_json tidak menyimpan

  3. tar gzip mongo dump seperti MySQL

  4. MongoDB - Tarik beberapa objek dari array

  5. Bagaimana Menemukan Indeks yang Tidak Digunakan di MongoDB?