Continuing on from Getting started with Spring Data and MongoDB we will look at implementing embedded documents.  This allows one to one and one to many relationships to be modelled within a document and allows data to be retrieved in a singular query. Although as more relationships are modelled through extra embedded documents the write performance onto it the parent document will decrease and cause fragmentation of the data.

That’s just a little introduction into embedded documents. In practice they are very straight forward to implement when using Spring Data as they are simply relations between objects where the document is the object and the embedded documents are fields within it.

In this post we will be using Spring Boot, the required setup and foundation information required for this post can be found in Getting started with Spring Data and MongoDB.

The main document object

The embedded documents

The only Spring Data specific annotations in these classes are the @Id and @Document annotations. @Id is only included in the Person class as this is the document that is persisted to the database whereas the Address and Hobby classes are embedded within it. The @Document annotation is needed so that a collection of embedded documents can be specified. In the Hobby class the @Document annotation specifies that it’s collection name is “hobbies” which is then referenced within Person. As seen by the Address class the annotation is also included but not used and therefore could be removed from the class, although this nicely demonstrates how both singular and plural versions can be used.

The next thing that we need to do is create an interface that extends MongoRepository<Person, String> which allows CRUD operations and our own defined methods to be used. As mentioned in my earlier post the MongoRepository infers the implementation of the method from the name on the interface allowing it be used without writing your own implementation. Although this not fully true for queries with relationships as a @Query annotation is required on the method definition that describes what the query does, but you still don’t need to write the method yourself!

Now all we need to do is create a class that has the @SpringBootApplication and @EnableMongoRepositories annotations and we are ready to see it in action.

Which when ran produces the following output

Find by first name
Person(firstName=John, secondName=Doe, address=Address(addressLineOne=19 Imaginary Road, addressLineTwo=Imaginary Place, city=Imaginary City, country=UK), profession=Winner, salary=100, hobbies=[Hobby(name=Badminton), Hobby(name=TV)])

Find by country (UK)
Person(firstName=John, secondName=Doe, address=Address(addressLineOne=19 Imaginary Road, addressLineTwo=Imaginary Place, city=Imaginary City, country=UK), profession=Winner, salary=100, hobbies=[Hobby(name=Badminton), Hobby(name=TV)])

Find by country (US)
Person(firstName=John, secondName=Doe, address=Address(addressLineOne=19 Imaginary Road, addressLineTwo=Imaginary Place, city=Imaginary City, country=US), profession=Winner, salary=100, hobbies=[Hobby(name=Badminton), Hobby(name=TV)])

As you can see both the queries that are defined on the interface have successfully retrieved the specified data and the change to the address was saved to the database via the saving of the Person object. When the original call to save is made the person collection is created which houses the single document that was produced. No such collections have been made for the embedded documents as they only reside inside the person documents.

Below is what the created document looks like

{
  "_id" : ObjectId("592c7029aafef820f432c5f3"),
  "_class" : "lankydan.tutorial.mongodb.documents.Person",
  "firstName" : "John",
  "secondName" : "Doe",
  "dateOfBirth" : ISODate("2017-05-29T20:02:01.636+01:00"),
  "address" : {
    "addressLineOne" : "19 Imaginary Road",
    "addressLineTwo" : "Imaginary Place",
    "city" : "Imaginary City",
    "country" : "US"
  },
  "profession" : "Winner",
  "salary" : 100,
  "hobbies" : [ 
    {
      "name" : "Badminton"
    }, 
    {
      "name" : "TV"
    }
  ]
}

You have now reached the end of this quick tutorial into Embedded documents with Spring Data and MongoDB where we have modelled relationships between data that are expressed as documents embedded within others.

If you want to play around with the code it can be found on my GitHub.