Ein Leitfaden für Abfragen in Spring Data MongoDB
1. Überblick
Dieser Artikel konzentriert sich auf den Aufbau verschiedenertypes of queries in Spring Data MongoDB.
Wir werden Dokumente mit den KlassenQuery undCriteria, automatisch generierten Abfragemethoden, JSON-Abfragen und QueryDSL abfragen.
Schauen Sie sich für das Maven-Setup unsereintroductory articlean.
2. Dokumentenabfrage
Eine der gebräuchlichsten Methoden zum Abfragen von MongoDB mit Spring Data ist die Verwendung der KlassenQuery undCriteria, die native Operatoren sehr genau widerspiegeln.
2.1. Is
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 NamenEric.
Schauen wir uns unsere Datenbank an:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.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 gibt erwartungsgemäß Folgendes zurück:
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
}
2.2. Regex
Eine flexiblere und leistungsfähigere Art der Abfrage ist der reguläre Ausdruck. Dieses c` ++ `wiederholt ein Kriterium unter Verwendung eines MongoDB$regex, das alle Datensätze zurückgibt, die für diesen regulären Ausdruck für dieses Feld geeignet sind.
Es funktioniert ähnlich wie die Operationen vonstartingWith, endingWith. Schauen wir uns ein Beispiel an.
Wir suchen jetzt nach allen Benutzern, deren Namen mitA beginnen.
Hier ist der Status der Datenbank:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.model.User",
"name" : "Antony",
"age" : 33
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581909"),
"_class" : "org.example.model.User",
"name" : "Alice",
"age" : 35
}
]
Erstellen wir nun die Abfrage:
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.example.model.User",
"name" : "Antony",
"age" : 33
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581909"),
"_class" : "org.example.model.User",
"name" : "Alice",
"age" : 35
}
]
Hier ist ein weiteres kurzes Beispiel, diesmal nach allen Benutzern zu suchen, deren Namen mitc 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.example.model.User",
"name" : "Eric",
"age" : 45
}
2.3. Lt undgt
Diese Operatoren erstellen ein Kriterium unter Verwendung des Operators$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 ist:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.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 mit einem Alter von mehr als 20 und weniger als 50 Jahren:
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
}
2.4. Sort
Sort wird verwendet, um eine Sortierreihenfolge für die Ergebnisse anzugeben.
Das folgende Beispiel gibt alle Benutzer in aufsteigender Reihenfolge nach Alter sortiert zurück.
Erstens - hier sind die vorhandenen Daten:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.model.User",
"name" : "Antony",
"age" : 33
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581909"),
"_class" : "org.example.model.User",
"name" : "Alice",
"age" : 35
}
]
Nach dem Ausführen vonsort:
Query query = new Query();
query.with(new Sort(Sort.Direction.ASC, "age"));
List users = mongoTemplate.find(query,User.class);
Und hier ist das Ergebnis der Abfrage - gut sortiert nachage:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.model.User",
"name" : "Antony",
"age" : 33
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581909"),
"_class" : "org.example.model.User",
"name" : "Alice",
"age" : 35
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
}
]
2.5. Pageable
Schauen wir uns ein kurzes Beispiel mit Paginierung an.
Hier ist der Status der Datenbank:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581907"),
"_class" : "org.example.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.model.User",
"name" : "Antony",
"age" : 33
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581909"),
"_class" : "org.example.model.User",
"name" : "Alice",
"age" : 35
}
]
Nun die Abfragelogik, einfach nach einer Seite der Größe 2 fragen:
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.example.model.User",
"name" : "Eric",
"age" : 45
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.model.User",
"name" : "Antony",
"age" : 33
}
]
3. Generierte Abfragemethoden
Lassen Sie uns nun den allgemeineren Abfragetyp untersuchen, den Spring Data normalerweise bereitstellt - automatisch generierte Abfragen aus Methodennamen.
Das einzige, was wir tun müssen, um diese Art von Abfragen zu nutzen, ist die Deklaration der Methode in der Repository-Schnittstelle:
public interface UserRepository
extends MongoRepository, QueryDslPredicateExecutor {
...
}
3.1. FindByX
Wir beginnen einfach mit der Untersuchung des Abfragetyps findBy. In diesem Fall suchen Sie nach Namen: __
List findByName(String name);
Wie im vorherigen Abschnitt - 2.1 - hat die Abfrage die gleichen Ergebnisse und findet alle Benutzer mit dem angegebenen Namen:
List users = userRepository.findByName("Eric");
3.2. StartingWith und endend mit.
In 2.2 haben wir eine aufregexbasierende Abfrage untersucht. Anfang und Ende mit sind natürlich weniger leistungsfähig, aber dennoch sehr nützlich - insbesondere, wenn wir sie nicht tatsächlich implementieren müssen.
Hier ist ein kurzes Beispiel, wie die Operationen aussehen würden: __
List findByNameStartingWith(String regexp);
List findByNameEndingWith(String regexp);
Das Beispiel, dies tatsächlich zu verwenden, wäre natürlich sehr einfach:
List users = userRepository.findByNameStartingWith("A");
List users = userRepository.findByNameEndingWith("c");
Und die Ergebnisse sind genau die gleichen.
3.3. Between
Ähnlich wie bei 2.3 werden alle Benutzer mit einem Alter zwischenageGT undageLT: zurückgegeben
List findByAgeBetween(int ageGT, int ageLT);
Der Aufruf der Methode führt dazu, dass genau die gleichen Dokumente gefunden werden:
List users = userRepository.findByAgeBetween(20, 50);
3.4. Like undOrderBy
Schauen wir uns diesmal ein erweitertes Beispiel an: Kombinieren Sie zwei Arten von Modifikatoren für die generierte Abfrage.
Wir werden nach allen Benutzern suchen, deren Namen den BuchstabenA enthalten, und wir werden die Ergebnisse auch nach Alter in aufsteigender Reihenfolge sortieren:
List users = userRepository.findByNameLikeOrderByAgeAsc("A");
Für die in 2.4 verwendete Datenbank lautet das Ergebnis:
[
{
"_id" : ObjectId("55c0e5e5511f0a164a581908"),
"_class" : "org.example.model.User",
"name" : "Antony",
"age" : 33
},
{
"_id" : ObjectId("55c0e5e5511f0a164a581909"),
"_class" : "org.example.model.User",
"name" : "Alice",
"age" : 35
}
]
4. JSON-Abfragemethoden
Wenn wir eine Abfrage nicht mithilfe eines Methodennamens oder von Kriterien darstellen können, können wir etwas niedrigeres tun -use the @Query annotation.
Mit dieser Annotation können wir eine unformatierte Abfrage als Mongo JSON-Abfragezeichenfolge angeben.
4.1. FindBy
Beginnen wir einfach und schauen wir uns an, wie wir zuersta find by type of methoddarstellen würden:
@Query("{ 'name' : ?0 }")
List findUsersByName(String name);
Diese Methode sollte Benutzer nach Namen zurückgeben - der Platzhalter?0verweist auf den ersten Parameter der Methode.
List users = userRepository.findUsersByName("Eric");
4.2 $regex
Schauen wir uns aucha regex driven query an - was natürlich das gleiche Ergebnis wie in 2.2 und 3.2 liefert:
@Query("{ 'name' : { $regex: ?0 } }")
List findUsersByRegexpName(String regexp);
Die Verwendung ist auch genau gleich:
List users = userRepository.findUsersByRegexpName("^A");
List users = userRepository.findUsersByRegexpName("c$");
4.3. $lt und$gt
Implementieren wir nun die Abfrage lt undgt:
@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")
List findUsersByAgeBetween(int ageGT, int ageLT);
Nun, da die Methode zwei Parameter hat, referenzieren wir jeden dieser Parameter nach Index in der Rohabfrage:?0 und?1.
List users = userRepository.findUsersByAgeBetween(20, 50);
5. QueryDSL-Abfragen
MongoRepository hat eine gute Unterstützung für das ProjektQueryDSL - daher können wir diese nette, typsichere API auch hier nutzen.
5.1. Die Maven-Abhängigkeiten
Stellen wir zunächst sicher, dass die richtigen Maven-Abhängigkeiten im POM definiert sind:
com.mysema.querydsl
querydsl-mongodb
3.6.6
com.mysema.querydsl
querydsl-apt
3.6.6
5.2. Q-Klassen
QueryDSL verwendete Q-Klassen zum Erstellen von Abfragen. Da wir diese jedoch nicht wirklich von Hand erstellen möchten, istwe need to generate themirgendwie.
Wir werden das apt-maven-Plugin verwenden, um das zu tun:
com.mysema.maven
apt-maven-plugin
1.1.3
process
target/generated-sources/java
org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
Schauen wir uns die KlasseUseran und konzentrieren uns dabei speziell auf die Annotation@QueryEntity:
@QueryEntity
@Document
public class User {
@Id
private String id;
private String name;
private Integer age;
// standard getters and setters
}
Nach dem Ausführen desprocess-Ziels des Maven-Lebenszyklus (oder eines anderen Ziels danach) - das passende Pluginwill generate the new classes untertarget/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);
}
}
Mit Hilfe dieser Klasse werden wir unsere Abfragen nicht erstellen.
Als Randnotiz: Wenn Sie Eclipse verwenden, wird durch die Einführung dieses Plugins die folgende Warnung in pom generiert:
Sie müssen build mit JDK ausführen oder tools.jar im Klassenpfad haben. Wenn dies während des Eclipse-Builds auftritt, stellen Sie sicher, dass Sie Eclipse auch unter JDK ausführen (com.mysema.maven: apt-maven-plugin: 1.1.3: process: default: generate-sources
Maveninstall funktioniert einwandfrei undQUser Klasse wird generiert, aber ein Plugin wird im POM hervorgehoben.
Eine schnelle Lösung besteht darin, manuell auf das JDK ineclipse.ini zu zeigen:
...
-vm
{path_to_jdk}\jdk{your_version}\bin\javaw.exe
5.3. The New Repository
Jetzt müssen wir die QueryDSL-Unterstützung in unseren Repositorys aktivieren - dies geschieht einfach mitextending the QueryDslPredicateExecutor interface:
public interface UserRepository extends
MongoRepository, QuerydslPredicateExecutor
5.4. Eq
Bei aktivierter Unterstützung sindlet’s now implement the same queries wie zuvor dargestellt.
Wir beginnen mit einer einfachen Gleichstellung:
QUser qUser = new QUser("user");
Predicate predicate = qUser.name.eq("Eric");
List users = (List) userRepository.findAll(predicate);
5.5. StartingWith undEndingWith
In ähnlicher Weise implementieren wir die vorherigen Abfragen - und suchen Benutzer mit Namen, die mitA beginnen:
QUser qUser = new QUser("user");
Predicate predicate = qUser.name.startsWith("A");
List users = (List) userRepository.findAll(predicate);
Und endend mitc:
QUser qUser = new QUser("user");
Predicate predicate = qUser.name.endsWith("c");
List users = (List) userRepository.findAll(predicate);
Das Ergebnis ist dasselbe wie in 2.2, 3.2 oder 4.2.
5.6. Between
Die nächste Abfrage gibt Benutzer mit einem Alter zwischen 20 und 50 Jahren zurück - ähnlich wie in den vorherigen Abschnitten:
QUser qUser = new QUser("user");
Predicate predicate = qUser.age.between(20, 50);
List users = (List) userRepository.findAll(predicate);
6. Fazit
In diesem Artikel haben wir die vielen Möglichkeiten untersucht, die wir mit Spring Data MongoDB abfragen können.
Es ist interessant, einen Schritt zurückzutreten und zu sehen, wie viele leistungsstarke Möglichkeiten wir haben, MongoDB abzufragen - von eingeschränkter Kontrolle bis hin zur vollständigen Kontrolle mit Rohabfragen.
Die Implementierung all dieser Beispiele und Codefragmentecan be found inthe GitHub project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.