1. Übersicht
Dieses Tutorial konzentriert sich auf den Aufbau verschiedener Arten von Abfragen in Spring Data MongoDB .
Wir werden uns das Abfragen von Dokumenten mit Query ansehen und Kriterien Klassen, automatisch generierte Abfragemethoden, JSON-Abfragen und QueryDSL.
Für die Einrichtung von Maven werfen Sie einen Blick auf unseren Einführungsartikel.
2. Dokumentenabfrage
Eine der gebräuchlicheren Methoden zum Abfragen von MongoDB mit Spring Data ist die Verwendung der Abfrage und Kriterien Klassen, die native Operatoren sehr genau widerspiegeln.
2.1. Ist
Dies ist einfach ein Kriterium, das Gleichheit verwendet. Mal sehen, wie es funktioniert.
Im folgenden Beispiel suchen wir nach Benutzern mit dem Namen Eric .
Sehen 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
}
}
Sehen wir uns nun den Abfragecode an:
Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eric"));
List<User> users = mongoTemplate.find(query, User.class);
Wie erwartet gibt diese Logik Folgendes zurück:
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.baeldung.model.User",
"name" : "Eric",
"age" : 45
}
2.2. Regex
Eine flexiblere und leistungsfähigere Abfrageart ist die Regex. Dadurch wird ein Kriterium mit einem $regex von MongoDB erstellt das alle Datensätze zurückgibt, die für die Regex für dieses Feld geeignet sind.
Es funktioniert ähnlich wie startingWith und endingWith Operationen.
In diesem Beispiel suchen wir nach allen Benutzern, deren Namen mit A beginnen .
Hier ist der Zustand 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
}
]
Jetzt erstellen wir die Abfrage:
Query query = new Query();
query.addCriteria(Criteria.where("name").regex("^A"));
List<User> 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, dieses Mal wird nach allen Benutzern gesucht, deren Namen mit c enden :
Query query = new Query();
query.addCriteria(Criteria.where("name").regex("c$"));
List<User> 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 unter Verwendung von $lt (kleiner als) und $gt (größer als) Operatoren.
Nehmen wir ein kurzes Beispiel, bei dem wir nach allen Benutzern im Alter zwischen 20 und 50 suchen.
Die Datenbank ist:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.baeldung.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.baeldung.model.User",
"name" : "Antony",
"age" : 55
}
}
Der Abfragecode:
Query query = new Query();
query.addCriteria(Criteria.where("age").lt(50).gt(20));
List<User> users = mongoTemplate.find(query,User.class);
Und die Ergebnisse für alle Nutzer mit einem Alter von über 20 und unter 50:
{
"_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.
Das folgende Beispiel gibt alle Benutzer sortiert nach Alter in aufsteigender Reihenfolge zurück.
Hier sind zunächst 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 von sortieren :
Query query = new Query();
query.with(Sort.by(Sort.Direction.ASC, "age"));
List<User> users = mongoTemplate.find(query,User.class);
Und hier ist das Ergebnis der Abfrage, schön sortiert nach Alter :
[
{
"_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. Seitenfähig
Schauen wir uns ein kurzes Beispiel mit Paginierung an.
Hier ist der Zustand 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
}
]
Hier ist nun die Abfragelogik, die einfach nach einer Seite der Größe 2 fragt:
final Pageable pageableRequest = PageRequest.of(0, 2);
Query query = new Query();
query.with(pageableRequest);
Und das Ergebnis, die 2 Dokumente, wie erwartet:
[
{
"_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. Generierte Abfragemethoden
Lassen Sie uns nun den häufigeren Abfragetyp untersuchen, den Spring Data normalerweise bereitstellt, nämlich automatisch generierte Abfragen aus Methodennamen.
Das Einzige, was wir tun müssen, um diese Art von Abfragen zu nutzen, ist, die Methode auf der Repository-Schnittstelle zu deklarieren:
public interface UserRepository
extends MongoRepository<User, String>, QueryDslPredicateExecutor<User> {
...
}
3.1. FindByX
Wir beginnen ganz einfach, indem wir den Abfragetyp findBy untersuchen. In diesem Fall verwenden wir die Suche nach Namen:
List<User> findByName(String name);
Genau wie im vorherigen Abschnitt, 2.1, wird die Abfrage dieselben Ergebnisse haben und alle Benutzer mit dem angegebenen Namen finden:
List<User> users = userRepository.findByName("Eric");
3.2. Beginntmit und endingWith
In Abschnitt 2.2 haben wir einen regex untersucht basierte Abfrage. Starts und Ends mit sind natürlich weniger leistungsfähig, aber dennoch recht nützlich, besonders wenn wir sie nicht wirklich implementieren müssen.
Hier ist ein kurzes Beispiel dafür, wie die Vorgänge aussehen würden:
List<User> findByNameStartingWith(String regexp);
List<User> findByNameEndingWith(String regexp);
Das Beispiel für die tatsächliche Verwendung wäre natürlich sehr einfach:
List<User> users = userRepository.findByNameStartingWith("A");
List<User> users = userRepository.findByNameEndingWith("c");
Und die Ergebnisse sind genau gleich.
3.3. Zwischen
Ähnlich wie in Abschnitt 2.3 werden hier alle Benutzer mit einem Alter zwischen ageGT zurückgegeben und ageLT:
List<User> findByAgeBetween(int ageGT, int ageLT);
Der Aufruf der Methode führt dazu, dass genau die gleichen Dokumente gefunden werden:
List<User> users = userRepository.findByAgeBetween(20, 50);
3.4. Gefällt mir und OrderBy
Schauen wir uns dieses Mal ein fortgeschritteneres Beispiel an, das zwei Arten von Modifikatoren für die generierte Abfrage kombiniert.
Wir werden nach allen Benutzern suchen, deren Namen den Buchstaben A, enthalten Außerdem ordnen wir die Ergebnisse nach Alter in aufsteigender Reihenfolge:
List<User> users = userRepository.findByNameLikeOrderByAgeAsc("A");
Für die Datenbank, die wir in Abschnitt 2.4 verwendet haben, lautet das Ergebnis:
[
{
"_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-Abfragemethoden
Wenn wir eine Abfrage nicht mit Hilfe eines Methodennamens oder von Kriterien darstellen können, können wir etwas auf niedrigerer Ebene tun, verwenden Sie @Query Anmerkung .
Mit dieser Anmerkung können wir eine Rohabfrage als Mongo-JSON-Abfragezeichenfolge angeben.
4.1. FindBy
Fangen wir einfach an und schauen uns an, wie wir ein Finden von darstellen würden Art der Methode zuerst:
@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);
Diese Methode sollte Benutzer nach Namen zurückgeben. Der Platzhalter?0 verweist auf den ersten Parameter der Methode.
List<User> users = userRepository.findUsersByName("Eric");
4.2. $regex
Wir können uns auch eine durch Regex gesteuerte Abfrage ansehen was natürlich das gleiche Ergebnis wie in den Abschnitten 2.2 und 3.2 liefert:
@Query("{ 'name' : { $regex: ?0 } }")
List<User> findUsersByRegexpName(String regexp);
Die Verwendung ist auch genau die gleiche:
List<User> users = userRepository.findUsersByRegexpName("^A");
List<User> users = userRepository.findUsersByRegexpName("c$");
4.3. $lt und $gt
Lassen Sie uns nun lt und gt implementieren Abfrage:
@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")
List<User> findUsersByAgeBetween(int ageGT, int ageLT);
Da die Methode nun 2 Parameter hat, referenzieren wir jeden von ihnen per Index in der Rohabfrage, ?0 und ?1:
List<User> users = userRepository.findUsersByAgeBetween(20, 50);
5. QueryDSL-Abfragen
MongoRepository bietet gute Unterstützung für das QueryDSL-Projekt, sodass wir diese nette, typsichere API auch hier nutzen können.
5.1. Die Maven-Abhängigkeiten
Stellen wir zunächst sicher, dass wir die richtigen Maven-Abhängigkeiten im pom definiert haben:
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-mongodb</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>4.3.1</version>
</dependency>
5.2.Q -Klassen
QueryDSL verwendete Q-Klassen zum Erstellen von Abfragen, aber da wir diese nicht wirklich von Hand erstellen wollen, müssen wir sie generieren irgendwie.
Dazu verwenden wir das apt-maven-plugin:
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>
org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
</processor>
</configuration>
</execution>
</executions>
</plugin>
Schauen wir uns den Benutzer an -Klasse, die sich speziell auf @QueryEntity konzentriert Anmerkung:
@QueryEntity
@Document
public class User {
@Id
private String id;
private String name;
private Integer age;
// standard getters and setters
}
Nach dem Ausführen des Prozesses Ziel des Maven-Lebenszyklus (oder jedes andere Ziel danach) wird das apt-Plugin die neuen Klassen generieren unter target/generated-sources/java/{Ihre Paketstruktur} :
/**
* QUser is a Querydsl query type for User
*/
@Generated("com.mysema.query.codegen.EntitySerializer")
public class QUser extends EntityPathBase<User> {
private static final long serialVersionUID = ...;
public static final QUser user = new QUser("user");
public final NumberPath<Integer> 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<? extends User> path) {
super(path.getType(), path.getMetadata());
}
public QUser(PathMetadata<?> metadata) {
super(User.class, metadata);
}
}
Aufgrund dieser Klasse müssen wir unsere Abfragen nicht erstellen.
Nebenbei bemerkt, wenn wir Eclipse verwenden, wird die Einführung dieses Plugins die folgende Warnung in pom generieren:
Die MavenInstallation funktioniert einwandfrei und der QUser Klasse generiert, aber ein Plugin wird im pom hervorgehoben.
Eine schnelle Lösung besteht darin, manuell auf das JDK in eclipse.ini zu verweisen :
...
-vm
{path_to_jdk}\jdk{your_version}\bin\javaw.exe
5.3. Das neue Repository
Jetzt müssen wir tatsächlich die QueryDSL-Unterstützung in unseren Repositorys aktivieren, was durch einfaches Erweitern des QueryDslPredicateExecutor erfolgt Schnittstelle :
public interface UserRepository extends
MongoRepository<User, String>, QuerydslPredicateExecutor<User>
5.4. Gl.
Wenn die Unterstützung aktiviert ist, lassen Sie uns jetzt dieselben Abfragen implementieren wie die, die wir zuvor illustriert haben.
Wir beginnen mit einfacher Gleichheit:
QUser qUser = new QUser("user");
Predicate predicate = qUser.name.eq("Eric");
List<User> users = (List<User>) userRepository.findAll(predicate);
5.5. Beginntmit und EndingWith
Lassen Sie uns auf ähnliche Weise die vorherigen Abfragen implementieren und Benutzer finden, deren Namen mit A beginnen :
QUser qUser = new QUser("user");
Predicate predicate = qUser.name.startsWith("A");
List<User> users = (List<User>) userRepository.findAll(predicate);
Sowie mit c endend :
QUser qUser = new QUser("user");
Predicate predicate = qUser.name.endsWith("c");
List<User> users = (List<User>) userRepository.findAll(predicate);
Das Ergebnis ist dasselbe wie in den Abschnitten 2.2, 3.2 und 4.2.
5.6. Zwischen
Die nächste Abfrage gibt Benutzer im Alter zwischen 20 und 50 zurück, ähnlich wie in den vorherigen Abschnitten:
QUser qUser = new QUser("user");
Predicate predicate = qUser.age.between(20, 50);
List<User> users = (List<User>) userRepository.findAll(predicate);