1. Übersicht
Dieser Artikel konzentriert sich auf das Erstellen verschiedener Arten von Abfragen in Spring Data MongoDB .
Wir werden uns die Abfrage von Dokumenten mit zu suchen Abfrage und Kriterien Klassen, automatisch generierte Abfragemethoden, JSON - Abfragen und QueryDSL.
Informationen zum Maven-Setup finden Sie in unserem Einführungsartikel.
2. Dokumentenabfrage
Eine der gebräuchlichsten Methoden zum Abfragen von MongoDB mit Spring Data ist die Verwendung der Klassen Query und Criteria , die native Operatoren sehr genau widerspiegeln.
2.1. Ist
Dies ist einfach ein Kriterium für die Verwendung von Gleichheit - mal sehen, wie es funktioniert.
Im folgenden Beispiel suchen wir nach Benutzern mit dem Namen Eric .
Schauen wir uns unsere Datenbank an:
[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 55 } }
Schauen wir uns nun den Abfragecode an:
Query query = new Query(); query.addCriteria(Criteria.where("name").is("Eric")); List users = mongoTemplate.find(query, User.class);
Diese Logik kehrt wie erwartet zurück:
{ "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }
2.2. Regex
Eine flexiblere und leistungsfähigere Art der Abfrage ist der reguläre Ausdruck. Dies erstellt ein Kriterium unter Verwendung eines MongoDB $ -Regex , der alle Datensätze zurückgibt, die für diesen Regexp für dieses Feld geeignet sind.
Es funktioniert ähnlich wie das Starten mit und Beenden mit Operationen - schauen wir uns ein Beispiel an.
Wir suchen jetzt nach allen Benutzern, deren Namen mit A beginnen .
Hier ist der Status der Datenbank:
[ { "_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 } ]
Lassen Sie uns nun die Abfrage erstellen:
Query query = new Query(); query.addCriteria(Criteria.where("name").regex("^A")); List users = mongoTemplate.find(query,User.class);
Dies wird ausgeführt und gibt 2 Datensätze zurück:
[ { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 33 }, { "_id" : ObjectId("55c0e5e5511f0a164a581909"), "_class" : "org.baeldung.model.User", "name" : "Alice", "age" : 35 } ]
Hier ist ein weiteres kurzes Beispiel, diesmal auf der Suche nach allen Benutzern, deren Namen mit c enden :
Query query = new Query(); query.addCriteria(Criteria.where("name").regex("c$")); List users = mongoTemplate.find(query, User.class);
Das Ergebnis wird also sein:
{ "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }
2.3. Lt und gt
Diese Operatoren erstellen ein Kriterium mit dem Operator $ lt (kleiner als) und $ gt (größer als).
Schauen wir uns ein kurzes Beispiel an - wir suchen alle Benutzer im Alter zwischen 20 und 50 Jahren.
Die Datenbank lautet:
[ { "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }, { "_id" : ObjectId("55c0e5e5511f0a164a581908"), "_class" : "org.baeldung.model.User", "name" : "Antony", "age" : 55 } }
Dieser Abfragecode:
Query query = new Query(); query.addCriteria(Criteria.where("age").lt(50).gt(20)); List users = mongoTemplate.find(query,User.class);
Und das Ergebnis - alle Benutzer, die älter als 20 Jahre und jünger als 50 Jahre sind:
{ "_id" : ObjectId("55c0e5e5511f0a164a581907"), "_class" : "org.baeldung.model.User", "name" : "Eric", "age" : 45 }
2.4. Sortieren
Sortieren wird verwendet, um eine Sortierreihenfolge für die Ergebnisse anzugeben.
Im folgenden Beispiel werden alle Benutzer in aufsteigender Reihenfolge nach Alter sortiert zurückgegeben.
Erstens - hier sind die vorhandenen Daten:
[ { "_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 } ]
Nach dem Ausführen der Sortierung :
Query query = new Query(); query.with(Sort.by(Sort.Direction.ASC, "age")); List users = mongoTemplate.find(query,User.class);
And here's the result of the query – nicely sorted by age:
[ { "_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. Pageable
Let's look at a quick example using pagination.
Here's the state of the database:
[ { "_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 } ]
Now, the query logic, simply asking for a page of size 2:
final Pageable pageableRequest = PageRequest.of(0, 2); Query query = new Query(); query.with(pageableRequest);
And the result – the 2 documents, as expected:
[ { "_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. Generated Query Methods
Let's now explore the more common type of query that Spring Data usually provides – auto-generated queries out of method names.
The only thing we need to do to leverage these kinds of queries is to declare the method on the repository interface:
public interface UserRepository extends MongoRepository, QueryDslPredicateExecutor { ... }
3.1. FindByX
We'll start simple, by exploring the findBy type of query – in this case, find by name:
List findByName(String name);
Same as in the previous section – 2.1 – the query will have the same results, finding all users with the given name:
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.