Data Modeling and Domain Objects

Introduction

In this lab you will have a chance to become better acquainted with the Couchify data models. There are a number of different ways to model data in JSON and you will have a chance to see some options and examine why one approach might work better than another for some scenarios.

What you will gain experience with:

  • Analyzing documents and their JSON constructs

  • Mapping scenarios to different JSON document models

Estimated time to complete: 45 minutes

Instructions

You will be performing all your work in the Capella Web console. If you have not already done so, open up a browser window to https://cloud.couchbase.com and log in with your Capella credentials.

Reviewing Data Models

Use Case

As you learned from the associated course, there are many different ways the data could be represented for the Couchify application based on a variety of different requirements. In this section, you will take time to analyze some of the key differences in the way the data is modeled in the playlist, userprofile and track documents.

Accessing documents in the buckets

In this section, you will be browsing documents representing the different ways of modeling Playlists, User details, Tracks and so on. You can easily do this by utilizing the Document viewer accessed from the Tools menu. To access this viewer, perform the following tasks.

The documents for each bucket in couchmusic1, couchmusic2 and couchmusic3 are stored in the couchify scope and in their respective collections. You will find that storing documents in the collections named by their types makes it very easy to select only the documents for the document type you are interested in simply by selecting the collection name. Browsing scope and collection

Analyzing couchmusic1

  1. Ensure that you are currently looking at documents in the couchmusic1 bucket.

  2. Examine any of the documents in any of the collections and notice that the document type is root node or attribute of the document.

  3. Select documents in the userprofile collection. Open one of the documents and note that the phones attribute is represented as a single object, which could potentially be a set of key/value pairs for different phone types.

  4. Select documents in the track collection. Open one of the documents and note that each track has an array of ratings, each of which can reference the userprofile document using the value for the username attribute.

  5. Select documents in the playlist collection. Open one of the documents and note that the tracks are merely an array of track id values. These can be used to build references to the documents of type track.

  6. Select documents in the country collection. Open one of the documents and note that the sub-region attribute references a simple embedded value as a String type.

Analyzing couchmusic2

Recall that the couchmusic2 bucket has documents stored in the couchify scope in individual collections for each document type.

  1. Use the Bucket selector (see above image) to switch to the couchmusic2 bucket. Then use the scope selector and collection selector to choose the desired scope and collection.

  2. Examine any of the documents and notice that, the type of document is no longer a root element, but is now just another attribute of the document.

  3. Select the userprofile collection. Open one of the documents and notice now that the phones attribute references an Array and each element of the Array is an object with multiple attributes.

  4. Select the track collection. Open one of the documents and note that in this version, an avg_rating attribute has been added.

  5. Select the playlist collection. Open one of the documents and note that this version includes an attribute called owner, which is an object containing partially duplicated data from the userprofile type document. This can make it easier to access key information from a playlist without having to fetch the associated User Profile document.

  6. Select the country collection. Open one of the documents and note that now, the region_number attribute references a number that can be used to access the new document type; sub-region

  7. Use the filter to select documents with the sub-region key prefix. Notice the data for a sub-region contains additional information, including its parent region.

Analyzing couchmusic3

  1. Use the Bucket selector (see above image) to switch to the couchmusic3 bucket.

  2. Select the userprofile collection. Open one of the documents and notice now that there is now an attribute called playlists, which is an Array of summary playlist information for all the playlists owned by this user. Why is this useful? Imagine upon login, a user may want to immediately see their playlists. With this minimal information embedded in the User Profile document, it is not necessary to perform a subsequent query to get the playlists.

  3. Select the track collection. Open one of the documents and note that rather than the ratings attribute referencing an array of rating objects, it now contains a set of objects, each of which is keyed by the username. This will be examined further in the next section.

  4. Select the playlist collection. Open one of the documents and notice now instead of the tracks attribute being a list of track ID, part of the track data is instead embedded for each track. With partial track data embedded in the playlist, it is no longer necessary to access the individual track documents in order to see details, such as the Artist, Song Title, link to the MP3 file, etc.

  5. Select the country collection. Open one of the documents and notice an additional attribute for updated, which is a timestamp of when the country data was last updated

  6. Select the sub-region collection. Open one of the documents and notice that an Array of country ID values has been added as a back reference. Why is this helpful? This allows navigation from both the country to the sub-region and from the sub-region back to the country.

Choosing a Domain Model

Using data model to enforce application business rules

Take a moment to think about the way in which the Couchify application will manage the rating of tracks. If a particular user were to rate a track more than once, what should the business rules be associated to that? Assuming you want to allow a user only one rating per track, how might this be enforced?

Use the selectors to select the track collection in the couchmusic1 bucket. Open one of the documents and notice with this structure, ratings are managed as an Array of ratings objects. Therefore, it is possible for a user to potentially create more than one rating unless strictly enforced by application business logic. Consider this fragment of the track document showing some of the ratings as an example.

    "ratings": [{
      "created": "2015-08-18T12:35:25",
      "rating": 3,
      "username": "optioninginlays85689"

    }, {
      "created": "2015-08-18T16:06:18",
      "rating": 4,
      "username": "boisterousnessinurement8"
    }, {
      "created": "2015-08-18T16:06:18",
      "rating": 4,
      "username": "boisterousnessinurement8"
    }, {
      "created": "2015-08-18T16:06:18",
      "rating": 4,
      "username": "boisterousnessinurement8"
    }],

This need not be taken care at the application end, this can be done implicitly based on the design of the data model. Switch to the couchmusic3 bucket and open one of the documents in the track collection. The document fragment below shows that rather than the ratings attribute referencing an array of rating objects, it now contains a set of objects, each of which is keyed by the username. The advantage of this data model is that if the user boisterousnessinurement8 rates the track multiple times, the ratings item will be over-written and multiple entries will not be accommodated.

    "ratings": {
      "boisterousnessinurement8": {
        "created": 1439931978000,
        "rating": 4
      },
      "optioninginlays85689": {
        "created": 1439919325000,
        "rating": 3
      }
    }

Relating Playlists and Owners

Imagine a scenario where you want the Couchify application to enable users to browse public playlists for tracks that they may wish to add to their own playlists. It may be of interest to know something of the owners first name, last name and picture of the owner. Using the data model for playlist documents from the couchmusic1 bucket, this would require a subsequent get() operations to fetch the userprofile document.

In the couchmusic2 bucket, note that part of the userprofile document are duplicated in the playlist document. Notice that whereas the owner attribute in couchmusic1 references a String value representing the username, in couchmusic2, this attributed references a JSON object.

{
  "created": "2014-12-16T17:30:45",
  "id": "0001b5ce-b28c-4e00-8a22-541f6728fa62",
  "name": "Playlist # 1 for Belen",
  "owner": {
    "created": 1432120440000,
    "firstName": "Belen",
    "lastName": "Ibañez",
    "picture": {
      "large": "https://randomuser.me/api/portraits/women/55.jpg",
      "medium": "https://randomuser.me/api/portraits/med/women/55.jpg",
      "thumbnail": https://randomuser.me/api/portraits/thumb/women/55.jpg
    },
    "title": "Miss",
    "updated": "2015-08-25T10:27:38",
    "username": "immunologistdispossession6223"
  },
["41D7B885A02A4550F883EEF58F7E29FF9FBE5B8F", "98B1A620AD95E0128639B9446FCDFC098C97E9F9", "136817E6BF9E9B8205896791B7306C4825600998", "DDDAB594A62D490AAC0BFAA4E7CAF142A0701406", "5F7A2165A85CC6A30A65A5E9CA73DE6DFA805357", "381F670B29F17E68E9D06C24E1F12A46BEB9FE42", "E560B4C81F9981ADE9B41AB69447192B33295D9A", "E7E018223C9C5350C61E131A902890CD0DA9C95E", "266FB2D4381E286DBF9918169B9C268FAABF9188"],
  "type": "playlist",
  "updated": "2015-09-11T10:39:48",
  "visibility": "PRIVATE"
}

What is the downside of duplicating part of this information in the playlist document? It is now necessary to ensure that the whenever the userprofile document is updated, all associated playlist documents must eventually be updated as well. Depending on the application requirements, the timing of this synchronization need not occur immediately.

Modeling for user login behavior

Consider a situation where in you need to login to the Couchify application which needs to show the user details as soon as you login along with the basic playlist information for playlists you own.

Using the couchmusic2 version of the userprofile document would require subsequent queries to get all associated playlists. However, the way userprofile is modeled in the couchmusic3 bucket allows for basic playlist information to be fetched along with the user details. The full details for an individual playlist can be fetched as needed.

{
   "userprofile":{
      "address":{
         "city":"jersey city",
         "countryCode":"US",
         "postalCode":47903,
         "state":"south carolina",
         "street":"5847 n stelling rd"
      },

      "created":1417745488000,
      "dateOfBirth":371106000000,
      "email":"nellie.henry@love.com",

      "favoriteGenres":[
         "Post-Bop",
         "Cabaret",
         "Power Metal"
      ],

      "firstName":"Nellie",
      "lastName":"Henry",

      "phones":[
         {
            "number":"(723)-066-7699",
            "type":"cell",
            "verified":1441998759876
         }
      ],

      "picture":{
         "large":"https://randomuser.me/api/portraits/women/69.jpg",
         "medium":"https://randomuser.me/api/portraits/med/women/69.jpg",
         "thumbnail":https://randomuser.me/api/portraits/thumb/women/69.jpg
      },

      "playlists":[
         {
            "created":1420284570000,
            "id":"2331fec0-757d-4af9-963f-5cb0877e3b23",
            "name":"Playlist # 4 for Nellie",
            "updated":1441985973000,
            "visibility":"PRIVATE"
         },

         {
            "created":1428650768000,
            "id":"4313f4e1-4cc0-4502-9313-53a9f371ff62",
            "name":"Playlist # 3 for Nellie",
            "updated":1441985973000,
            "visibility":"PRIVATE"
         },

         {
            "created":1437099149000,
            "id":"ab723fc3-fd8f-4bde-99d0-d8f58353e631",
            "name":"Playlist # 5 for Nellie",
            "updated":1441985973000,
            "visibility":"PUBLIC"
         },

         {
            "created":1413115145000,
            "id":"d38221da-ac70-4c48-ae4c-1becb2773fd3",
            "name":"Playlist # 2 for Nellie",
            "updated":1441985973000,
            "visibility":"PRIVATE"
         },

         {
            "created":1430897658000,
            "id":"ff88b2b7-5afb-4b27-8aca-e7ad50e4ac7d",
            "name":"Playlist # 1 for Nellie",
            "updated":1441985973000,
            "visibility":"PUBLIC"
         }
      ],

      "pwd":"6962616e657a",
      "status":"active",
      "title":"Ms",
      "updated":1440516518000,
      "username":"abacusesthronging42801"
   }
}

Consider the ways in which playlists and tracks may be presented to the Couchify user. Playlists may be offered under two different scenarios; opening a playlist to play the songs and the former scenario where you wish to allow other users to browse public playlists. In the case of user opening a playlist, they may wish to review the details of the individual tracks as well. In this case, the playlist defined in the couchmusic2 will require a series of additional get() operations to fetch each of the track details. However, the playlist document defined in the couchmusic3 bucket embeds part of the track details.

{
  "playlist": {
    "created": 1428766518000,
    "id": "0002903e-e6f0-4e8f-94c0-18e80a19636f",
    "name": "Playlist # 1 for Kristen",
    "owner": {
      "created": 1419670543000,
      "firstName": "Kristen",
      "lastName": "Allen",

      "picture": {
        "large": "https://randomuser.me/api/portraits/women/69.jpg",
        "medium": "https://randomuser.me/api/portraits/med/women/69.jpg",
        "thumbnail": https://randomuser.me/api/portraits/thumb/women/69.jpg
      },

      "title": "Mrs",
      "updated": 1440516619000,
      "username": "vincibleplucky88570"
    },

    "tracks": [{
      "artist": "Wendy Carlos",
      "genre": "Experimental Electronic",
      "id": "31D4DBA236EE25926BCEF25F0A20E1D0B3C4410C",
      "mp3": "https://stream.song365.co/h/1276486/Wendy%20Carlos%20-%20Danny%20Bells%20Ascending%28From%20%22The%20Shining%22%29_(song365.cc).mp3",
      "title": "Danny Bells Ascending(From \"The Shining\")",
      "updated": 1439987185000
    }, {

      "artist": "Alvin Lucier",
      "genre": "Experimental Electronic",
      "id": "3E87B3ECD1C0FA060C58A144F813C833E6A1CD60",
      "mp3": "https://stream.song365.co/h/1076591/Alvin%20Lucier%20-%20Violin%20Solo_(song365.cc).mp3",
      "title": "Violin Solo",
      "updated": 1439860588000
    }, {

      "artist": "Nicolas Collins",
      "genre": "Experimental Electronic",
      "id": "CBF61EA93DA73ED39D454E0F8163147D5C99774A",
      "mp3": "https://stream.song365.co/h/367212/Nicolas%20Collins%20-%20Tobabo%20Fonio_(song365.cc).mp3",
      "title": "Tobabo Fonio",
      "updated": 1439943364000
    }, {

      "artist": "Harold Budd",
      "genre": "Experimental Electronic",
      "id": "5A0A98320000A10596B7C75B4ED4744092773EE4",
      "mp3": "https://stream.song365.co/h/675584/Harold%20Budd%20-%20Postlude_(song365.cc).mp3",
      "title": "Postlude",
      "updated": 1439917720000
    }, {

      "artist": "Peter Hammill",
      "genre": "Experimental Electronic",
      "id": "DFDD9CDD47DD0E3BD1C4FA4BA53D3CEFD253C0F2",
      "mp3": "https://stream.song365.co/h/176001/Peter%20Hammill%20-%20Golden%20Promises_(song365.cc).mp3",
      "title": "Golden Promises",
      "updated": 1439945848000
    }, {

      "artist": "Deuter",
      "genre": "Experimental Electronic",
      "id": "E1217FE25F736426E0CD612501D8C12083EFD78E",
      "mp3": "https://stream.song365.co/h/900860/Deuter%20-%20Buddha%20Nature_(song365.cc).mp3",
      "title": "Buddha Nature",
      "updated": 1439901148000
    }, {

      "artist": "Beaver \u0026 Krause",
      "genre": "Experimental Electronic",
      "id": "02D853E7E585375D851BBCF87B1BA7E8F93417B1",
      "mp3": "https://stream.song365.co/h/99948/Beaver%20%26%20Krause%20-%20Bluebird%20Canyon%20Stomp_(song365.cc).mp3",
      "title": "Bluebird Canyon Stomp",
      "updated": 1439866453000
    }],
    "updated": 1441986006000,
    "visibility": "PRIVATE"
  }
}

Lab summary

In this lab you had a chance to become more familiar with the ways in which data related to the Couchify application can be modeled.

  • You looked at different ways in which the documents could be structured and saw clear differences between referencing other documents and partially or fully embedding data from related documents within the document in question.

  • You examined different scenarios that might dictate these different ways of modeling data.

Congratulations. You have completed this lab.

results matching ""

    No results matching ""