Spring Data MongoDB - Indekser, merknader og omformere

1. Oversikt

Denne opplæringen vil utforske noen av kjernefunksjonene i Spring Data MongoDB - indeksering, vanlige merknader og omformere.

2. Indekser

2.1. @Indexed

Denne kommentaren markerer feltet som indeksert i MongoDB:

@QueryEntity @Document offentlig klasse bruker {@Indexed privat strengnavn; ...}

Nå som Navn feltet er indeksert - la oss ta en titt på indeksene i MongoDB:

db.user.getIndexes ();

Her er hva vi har på databasenivå:

[{"v": 1, "key": {"_id": 1}, "name": "_id_", "ns": "test.user"}, {"v": 1, "key": {"name": 1}, "name": "name", "ns": "test.user"}]

Som du kan se, har vi to indekser - en av dem er _id - som ble opprettet som standard på grunn av @Id kommentar og den andre er vår Navn felt.

2.2. Lag en indeks programmatisk

Vi kan også lage en indeks programmatisk:

mongoOps.indexOps (User.class). sikreIndex (ny indeks (). on ("navn", Direction.ASC)); 

Vi har nå opprettet en indeks for feltet Navn og resultatet blir det samme som i forrige avsnitt.

2.3. Sammensatte indekser

MongoDB støtter sammensatte indekser, der en enkelt indeksstruktur inneholder referanser til flere felt.

La oss se et raskt eksempel ved å bruke sammensatte indekser:

@QueryEntity @Document @CompoundIndexes ({@CompoundIndex (name = "email_age", def = "{'email.id': 1, 'age': 1}")}) offentlig klasse bruker {//}

Vi opprettet en sammensatt indeks med e-post og alder Enger. La oss nå sjekke ut de faktiske indeksene:

{"v": 1, "key": {"email.id": 1, "age": 1}, "name": "email_age", "ns": "test.user"} 

Merk at a DBRef feltet kan ikke merkes med @Index - det feltet kan bare være en del av en sammensatt indeks.

3. Vanlige merknader

3.1 @Flyktig

Som du forventer, ekskluderer denne enkle kommentaren feltet fra å være vedvarende i databasen:

offentlig klasse bruker {@Transient private Integer yearOfBirth;
 // standard getter og setter}

La oss sette inn bruker med innstillingsfeltet fødselsår:

Brukerbruker = ny bruker (); user.setName ("Alex"); user.setYearOfBirth (1985); mongoTemplate.insert (bruker); 

Nå hvis vi ser på tilstanden til databasen, ser vi at den arkiverte fødselsår ble ikke lagret:

{"_id": ObjectId ("55d8b30f758fd3c9f374499b"), "name": "Alex", "age": null}

Så hvis vi spør og sjekker:

mongoTemplate.findOne (Query.query (Criteria.where ("name"). is ("Alex")), User.class) .getYearOfBirth ()

Resultatet blir null.

3.2. @Felt

@Felt indikerer nøkkelen som skal brukes til feltet i JSON-dokumentet:

@Field ("e-post") privat EmailAddress emailAddress; 

epostadresse lagres i databasen ved hjelp av nøkkelen e-post:

Brukerbruker = ny bruker (); user.setName ("Brendan"); EmailAddress emailAddress = ny EmailAddress (); emailAddress.setValue ("[email protected]"); user.setEmailAddress (emailAddress); mongoTemplate.insert (bruker); 

Og databasens tilstand:

{"_id": ObjectId ("55d076d80bad441ed114419d"), "name": "Brendan", "age": null, "email": {"value": "[email protected]"}}

3.3. @PersistenceConstructor og @Verdi

@PersistenceConstructor markerer en konstruktør, til og med en som er pakkebeskyttet, for å være den primære konstruktøren som brukes av utholdenhetslogikken. Konstruktørargumentene tilordnes med navn til nøkkelverdiene i den hentede DBObject.

La oss se på denne konstruktøren for vår Bruker klasse:

@PersistenceConstructor offentlig bruker (strengnavn, @Value ("# root.age?: 0") Heltal alder, EmailAddress emailAddress) {this.name = name; this.age = alder; this.emailAddress = emailAddress; } 

Legg merke til bruken av standardfjæren @Verdi kommentar her. Det er ved hjelp av denne merknaden at vi kan bruke Spring Expressions til å transformere en nøkkelverdi hentet fra databasen før den brukes til å konstruere et domeneobjekt. Det er en veldig kraftig og svært nyttig funksjon her.

I vårt eksempel hvis alder er ikke satt til at det vil bli satt til 0 som standard.

La oss nå se hvordan det fungerer:

Brukerbruker = ny bruker (); user.setName ("Alex"); mongoTemplate.insert (bruker);

Databasen vår vil se ut:

{"_id": ObjectId ("55d074ca0bad45f744a71318"), "name": "Alex", "age": null}

alder feltet er null, men når vi spør etter dokumentet og henter det alder:

mongoTemplate.findOne (Query.query (Criteria.where ("name"). is ("Alex")), User.class) .getAge ();

Resultatet blir 0.

4. Omformere

La oss nå ta en titt på en annen veldig nyttig funksjon i Spring Data MongoDB - omformere, og spesielt på MongoConverter.

Dette brukes til å håndtere kartleggingen av alle Java-typer til DBO-objekter når du lagrer og spørre etter disse objektene.

Vi har to alternativer - vi kan enten jobbe med MappingMongoConverter - eller SimpleMongoConverter i tidligere versjoner (dette ble avviklet i Spring Data MongoDB M3 og funksjonaliteten er flyttet inn MappingMongoConverter).

Eller vi kan skrive vår egen tilpassede omformer. For å gjøre det, må vi implementere Konverter grensesnitt og registrere implementeringen i MongoConfig.

La oss se på et raskt eksempel. Som du har sett i noen av JSON-utdataene her, har alle objekter som er lagret i en database feltet _klasse som lagres automatisk. Hvis vi imidlertid vil hoppe over det aktuelle feltet under utholdenhet, kan vi gjøre det ved hjelp av a MappingMongoConverter.

Først - her er den tilpassede konverteringsimplementeringen:

@Component public class UserWriterConverter implementerer Converter {@Override public DBObject convert (User user) {DBObject dbObject = new BasicDBObject (); dbObject.put ("navn", user.getName ()); dbObject.put ("alder", user.getAge ()); hvis (user.getEmailAddress ()! = null) {DBObject e-postDbObject = ny BasicDBObject (); emailDbObject.put ("verdi", user.getEmailAddress (). getValue ()); dbObject.put ("e-post", emailDbObject); } dbObject.removeField ("_ class"); returner dbObject; }}

Legg merke til hvordan vi lett kan nå målet om ikke å vedvare _klasse ved å spesifikt fjerne feltet direkte her.

Nå må vi registrere den tilpassede omformeren:

privat liste omformere = ny ArrayList(); @Override public MongoCustomConversions customConversions () {converters.add (ny UserWriterConverter ()); returner nye MongoCustomConversions (omformere); }

Vi kan selvfølgelig oppnå det samme resultatet med XML-konfigurasjon også hvis vi trenger å:

Nå, når vi lagrer en ny bruker:

Brukerbruker = ny bruker (); user.setName ("Chris"); mongoOps.insert (bruker); 

Det resulterende dokumentet i databasen inneholder ikke lenger klasseinformasjonen:

{"_id": ObjectId ("55cf09790bad4394db84b853"), "name": "Chris", "age": null}

5. Konklusjon

I denne veiledningen har vi dekket noen kjernekonsepter for å jobbe med Spring Data MongoDB - indeksering, vanlige merknader og omformere.

Implementeringen av alle disse eksemplene og kodebiter finner du i mitt github-prosjekt.