Panduan untuk Pertanyaan di Spring Data MongoDB

1. Gambaran keseluruhan

Artikel ini akan memberi tumpuan untuk membina pelbagai jenis pertanyaan dalam Spring Data MongoDB .

Kami akan melihat dokumen pertanyaan dengan kelas Pertanyaan dan Kriteria , kaedah pertanyaan yang dihasilkan secara automatik, pertanyaan JSON dan QueryDSL.

Untuk persediaan Maven, lihat artikel pengenalan kami.

2. Pertanyaan Dokumen

Salah satu cara yang lebih biasa untuk menanyakan MongoDB dengan Spring Data adalah dengan menggunakan kelas Pertanyaan dan Kriteria - yang sangat mencerminkan operator asli.

2.1. Adakah

Ini hanyalah kriteria menggunakan persamaan - mari kita lihat bagaimana ia berfungsi.

Dalam contoh berikut - kami mencari pengguna bernama Eric .

Mari lihat pangkalan data kami:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 55 } }

Sekarang mari kita lihat kod pertanyaan:

Query query = new Query(); query.addCriteria(Criteria.where("name").is("Eric")); List users = mongoTemplate.find(query, User.class); 

Logik ini kembali, seperti yang diharapkan:

{ "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }

2.2. Regex

Jenis pertanyaan yang lebih fleksibel dan kuat adalah regex. Ini mengemukakan kriteria menggunakan MongoDB $ regex yang mengembalikan semua rekod yang sesuai untuk regexp ini untuk bidang ini.

Ia berfungsi serupa dengan operasi startWith, endingWith - mari kita lihat contohnya.

Kami sedang mencari untuk semua pengguna yang mempunyai nama bermula dengan A .

Inilah keadaan pangkalan data:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 } ]

Sekarang mari buat pertanyaan:

Query query = new Query(); query.addCriteria(Criteria.where("name").regex("^A")); List users = mongoTemplate.find(query,User.class);

Ini berjalan dan mengembalikan 2 rekod:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 } ]

Inilah contoh cepat lain, kali ini mencari semua pengguna yang mempunyai nama yang diakhiri dengan c :

Query query = new Query(); query.addCriteria(Criteria.where("name").regex("c$")); List users = mongoTemplate.find(query, User.class); 

Maka hasilnya akan:

{ "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }

2.3. Lt dan gt

Operator ini membuat kriteria menggunakan operator $ lt (kurang daripada) dan $ gt (lebih besar daripada).

Mari lihat contohnya dengan cepat - kami mencari semua pengguna dengan usia antara 20 dan 50 tahun.

Pangkalan data adalah:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 55 } }

Kod pertanyaan ini:

Query query = new Query(); query.addCriteria(Criteria.where("age").lt(50).gt(20)); List users = mongoTemplate.find(query,User.class); 

Dan hasilnya - semua pengguna yang berumur lebih dari 20 tahun dan kurang dari 50 tahun:

{ "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }

2.4. Susun

Urutkan digunakan untuk menentukan urutan urutan untuk hasil.

Contoh di bawah mengembalikan semua pengguna yang disusun mengikut umur mengikut urutan menaik.

Pertama - inilah data yang ada:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 } ] 

Setelah melaksanakan urutan :

Query query = new Query(); query.with(Sort.by(Sort.Direction.ASC, "age")); List users = mongoTemplate.find(query,User.class); 

Dan inilah hasil pertanyaan - disusun dengan baik mengikut umur :

[ { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 }, { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 } ]

2.5. Muka surat

Mari lihat contoh ringkas menggunakan penomboran.

Inilah keadaan pangkalan data:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 } ] 

Sekarang, logik pertanyaan, hanya meminta halaman ukuran 2:

final Pageable pageableRequest = PageRequest.of(0, 2); Query query = new Query(); query.with(pageableRequest); 

Dan hasilnya - 2 dokumen, seperti yang diharapkan:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 } ]

3. Kaedah Pertanyaan yang dihasilkan

Sekarang mari kita meneroka jenis pertanyaan yang lebih biasa yang biasanya disediakan oleh Spring Data - pertanyaan yang dijana secara automatik daripada nama kaedah.

Satu-satunya perkara yang perlu kita lakukan untuk memanfaatkan pertanyaan seperti ini adalah dengan menyatakan kaedah di antara muka repositori:

public interface UserRepository extends MongoRepository, QueryDslPredicateExecutor { ... }

3.1. CariByX

Kami akan mula mudah, dengan meneroka jenis pertanyaan findBy - dalam kes ini, cari dengan nama:

List findByName(String name);

Sama seperti pada bahagian sebelumnya - 2.1 - pertanyaan akan mempunyai hasil yang sama, mencari semua pengguna dengan nama yang diberikan:

List users = userRepository.findByName("Eric"); 

3.2. StartingWith and endingWith.

In 2.2, we explored a regex based query. Starts and ends with are of course less powerful, but nevertheless quite useful – especially if we don't have to actually implement them.

Here's a quick example of how the operations would look like:

List findByNameStartingWith(String regexp);
List findByNameEndingWith(String regexp);

The example of actually using this would, of course, be very simple:

List users = userRepository.findByNameStartingWith("A"); 
List users = userRepository.findByNameEndingWith("c");

And the results are exactly the same.

3.3. Between

Similar to 2.3, this will return all users with age between ageGT and ageLT:

List findByAgeBetween(int ageGT, int ageLT);

Calling the method will result in exactly the same documents being found:

List users = userRepository.findByAgeBetween(20, 50); 

3.4. Like and OrderBy

Let's have a look at a more advanced example this time – combining two types of modifiers for the generated query.

We're going to be looking for all users that have names containing the letter A and we're also going to order the results by age, in ascending order:

List users = userRepository.findByNameLikeOrderByAgeAsc("A"); 

For the database we used in 2.4 – the result will be:

[ { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 } ]

4. JSON Query Methods

If we can't represent a query with the help of a method name, or criteria, we can do something more low level – use the @Query annotation.

With this annotation, we can specify a raw query – as a Mongo JSON query string.

4.1. FindBy

Let's start simple and look at how we would represent a find by type of method first:

@Query("{ 'name' : ?0 }") List findUsersByName(String name); 

This method should return users by name – the placeholder ?0 references the first parameter of the method.

List users = userRepository.findUsersByName("Eric");

4.2 $regex

Let's also look at a regex driven query – which of course produces the same result as in 2.2 and 3.2:

@Query("{ 'name' : { $regex: ?0 } }") List findUsersByRegexpName(String regexp);

The usage is also exactly the same:

List users = userRepository.findUsersByRegexpName("^A"); 
List users = userRepository.findUsersByRegexpName("c$");

4.3. $lt and $gt

Let's now implement the lt and gt query:

@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }") List findUsersByAgeBetween(int ageGT, int ageLT);

Now how, now that the method has 2 parameters, we're referencing each of these by index in the raw query: ?0 and ?1.

List users = userRepository.findUsersByAgeBetween(20, 50);

5. QueryDSL Queries

MongoRepository has good support for the QueryDSL project – so we can leverage that nice, type-safe API here as well.

5.1. The Maven Dependencies

First, let's make sure we have the correct Maven dependencies defined in the pom:

 com.mysema.querydsl querydsl-mongodb 4.3.1 com.mysema.querydsl querydsl-apt 4.3.1 

5.2. Q-classes

QueryDSL used Q-classes for creating queries. But, since we don't really want to create these by hand, we need to generate them somehow.

We're going to use the apt-maven-plugin to do that:

 com.mysema.maven apt-maven-plugin 1.1.3 process target/generated-sources/java org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor 

Let's look at the User class – focusing specifically at the @QueryEntity annotation:

@QueryEntity @Document public class User { @Id private String id; private String name; private Integer age; // standard getters and setters }

After running the process goal of the Maven lifecycle (or anything another goal after that one) – the apt plugin will generate the new classes under target/generated-sources/java/{your package structure}:

/** * QUser is a Querydsl query type for User */ @Generated("com.mysema.query.codegen.EntitySerializer") public class QUser extends EntityPathBase { private static final long serialVersionUID = ...; public static final QUser user = new QUser("user"); public final NumberPath age = createNumber("age", Integer.class); public final StringPath id = createString("id"); public final StringPath name = createString("name"); public QUser(String variable) { super(User.class, forVariable(variable)); } public QUser(Path path) { super(path.getType(), path.getMetadata()); } public QUser(PathMetadata metadata) { super(User.class, metadata); } }

It's with the help of this class that we're not going to be creating our queries.

As a side note – if you're using Eclipse, introducing this plugin will generate the following warning in pom:

You need to run build with JDK or have tools.jar on the classpath. If this occurs during eclipse build make sure you run eclipse under JDK as well (com.mysema.maven:apt-maven-plugin:1.1.3:process:default:generate-sources

Maven install works fine and QUser class is generated, but a plugin is highlighted in the pom.

A quick fix is to manually point to the JDK in eclipse.ini:

... -vm {path_to_jdk}\jdk{your_version}\bin\javaw.exe

5.3. The New Repository

Now we need to actually enable QueryDSL support in our repositories – which is done by simply extending the QueryDslPredicateExecutor interface:

public interface UserRepository extends MongoRepository, QuerydslPredicateExecutor

5.4. Eq

With support enabled, let's now implement the same queries as the ones we illustrated before.

We'll start with simple equality:

QUser qUser = new QUser("user"); Predicate predicate = qUser.name.eq("Eric"); List users = (List) userRepository.findAll(predicate);

5.5. StartingWith and EndingWith

Similarly, let's implement the previous queries – and find users with names that are starting with A:

QUser qUser = new QUser("user"); Predicate predicate = qUser.name.startsWith("A"); List users = (List) userRepository.findAll(predicate); 

And ending with c:

QUser qUser = new QUser("user"); Predicate predicate = qUser.name.endsWith("c"); List users = (List) userRepository.findAll(predicate); 

The result with same as in 2.2, 3.2 or 4.2.

5.6. Between

The next one query will return users with age between 20 and 50 – similar to the previous sections:

QUser qUser = new QUser("user"); Predicate predicate = qUser.age.between(20, 50); List users = (List) userRepository.findAll(predicate);

6. Conclusion

In this article, we explored the many ways we can query using Spring Data MongoDB.

It's interesting to take a step back and see just how many powerful ways we have to query MongoDB – varying from limited control all the way to full control with raw queries.

The implementation of all these examples and code snippets can be found in the GitHub project.