Apply the Polymorphic Pattern Lab

Ok… I read the other post about this and I could not see what they did to get this to pass… Can someone look at how I formatted this and provide any recommendations.

I figured the best approach would be to embed the book, ebook, and audiobook into the document as subdocuments. Here is the syntax that I used, but it fails validation.

[
    {   "_id":"<objectId>",
        "product_id": "<int>",
        "title": "<string>",
        "description": "<string>",
        "authors": ["<string>"],
        "format": [ {"book":
                        { "publisher": "<string>",
                            "language": "<string>",
                            "pages": "<int>",
                            "catalogues":  
                            {
                                "isbn10": "<string>",
                                "isbn13": "<string>"
                            }
                        }, 
                    "ebook":
                        {  "format": "ebook",
                            "publisher": "<string>",
                            "language": "<string>",
                            "eformats": 
                                {
                                    "epub": 
                                        {
                                            "pages": "<int>"
                                        },
                                    "pdf": 
                                        {
                                            "pages": "<int>"
                                        }
                                },
                            "isbn10": "<string>"
                        },
                   "audiobook":
                        {
                            "narrator": "<string>",
                            "publisher": "<string>",
                            "language": "<string>",
                            "length_minutes": "<int>"
                        }
                    }
                ]
    }
]

I believe this format is correct, but I cannot get it to pass validation. I removed the description from the specific documents and included it in the common area along with the author field. The product_id is also common (removed from the individual entries)… Any guidance would be appreciated… Even if it is a link to read for myself and figure out.
Thanks.

Hi @David_44057

I think there are a couple of related issues in this schema that essentially can be summarized into the vast majority of the fields can be at the top level of the document and don’t require the nesting outlined above.

For example, to concrete highlight this, the following fields should all be present at the top level of the document:

  "publisher": "<string>",
  "language": "<string>",
  "pages": "<int>",
  "catalogues":  
  {
      "isbn10": "<string>",
      "isbn13": "<string>"
  }

Most of the fields can exist in the top level and don’t need to be nested under the type of book. The ability for MongoDB’s documents to have multiple dynamic schema or in this case where multiple books can be stored in documents, where there are several common fields but for the likes of audio books, the narrator field is only present in those documents with the format being audio book. These fields don’t need need to be nested.

This is somewhat new and unusual thinking if you have relational database experience and the freedom of the document model around this can take a little time to become familiar with.

I hope this helps and clarifies what will help your next steps to completing this lesson.

Kindest regards,
Eoin

Ok… I am starting to see my hang up… However, when I looked at this again and saw multiple fields that are the same, I moved them all into the top document… This effectively removed ALL fields from the book format. So… I updated it with the following…

[
    {   "_id":"<objectId>",
        "product_id": "<int>",
        "title": "<string>",
        "description": "<string>",
        "authors": ["<string>"],
        "catalogues":  
            {
                "isbn10": "<string>",
                "isbn13": "<string>"
            },
        "publisher": "<string>",
        "language": "<string>",
        "pages": "<int>",
        "length_minutes": "<int>",
        "format": [
                    "book",{
                     "ebook":
                        {
                            "eformats": 
                                {
                                    "epub": 
                                        {
                                            "pages": "<int>"
                                        },
                                    "pdf": 
                                        {
                                            "pages": "<int>"
                                        }
                                }
                        },
                     "audiobook":
                        {
                            "narrator": "<string>"
                            
                        }
                    }
                ]
    }
]

However when running this, it also fails validation… I have the --verbose flag on the command, but all it says is that the document fails validation. So there is no reference as to what is happening for me to troubleshoot.

The only thing that I can see is that the “pages”: “” field and the “length_minutes”: “” fields need to me moved back to the respective format break downs.

Am I going in the right direction??

This is what I get from validation:

PS D:\65945\m320> ./validate_m320 pattern_polymorphic --file pattern_polymorphic.json --verbose
Answer Filename: D:/65945/m320/pattern_polymorphic.json

Processing document: 1

  ... against solution: 1
The document fails validation.

Errors:
At least one of your solutions is not passing validation.

This is the lab requirements:

Task

To address the schema changes, we will use the Polymorphic Pattern to identify the shape of each document depending on its format.

We will make the following modifications to our current schemas to have all documents share some common elements:

Across all documents, we will use a new field called format that will have a value of book, ebook, or audiobook.
Across all documents, we will have a field called product_id that will accept an integer as its value.
The field description should be unified across all documents.
The field authors should be unified across all documents.
To complete this task, complete the following steps:

Modify the following schemas to incorporate the changes stated above:

Based on the lab requirements, I am moving more than is asked… Is this supposed to happen or am I only supposed to move the items to meet the task requirements?

Hi @David_44057

You’re getting closer to the solution, you are adding additional complexity to the task and lesson as it stands.

Building on what I outlined earlier, you should be planning to reduce the nesting in the document. Essentially, to extend what you have you should consider refactoring your schema above to reduce this. Looking at the “format” sub-document, I’ll give a hint that this could be re-written to say “eformats” with a field “epub” which has a field “pages”. This would drop the “format” and several of the fields in that hierarchy whilst still retaining all the data as the nested fields outlined don’t actually add new information and can be dropped.

Here’s a snippet of what I mean:
“eformats”: {
“epub”: {
“pages”: “”
}, <… more eformats …>

Essentially, reducing the schema further will help firstly to pass the validation but more importantly, I hope to show how the document model can be simplified in terms of the document structure but still convey the same information.

Schema modelling and schema design are complex, the freedom of the document model means anything can go but when you try to apply validation you should always reflect on the schema to make it the simplest possible for your needs. It’s not to say you can’t use your suggested schema but I hope I have highlighted some additional factors you will consider when modelling going forward.

Specifically, in terms of the validators of this course, the many many potential solutions can’t be coded and the correct solution has been boiled down to the simplest essential solution. This is how you should approach the rest of the exercises going forward in the course and the KISS principle in schema design often give a good, if not the best design in the vast majority of cases.

Kindest regards and hope this helps,
Eoin

Thanks for the clarification… I do need to point out that while your explanation is really good… If you read the lab, there is a lot of room for misinterpretation.

The lab states:

Across all documents, we will use a new field called format that will have a value of book, ebook, or audiobook.

This led me to believe that there is a “need” for the field and that it will be looked for in the solution check… I understand the idea to remove as many common fields as possible in the nesting, but I’m going to post the words of the requirements in the lab.

We will make the following modifications to our current schemas to have all documents share some common elements:

Across all documents, we will use a new field called format that will have a value of book, ebook, or audiobook.
Across all documents, we will have a field called product_id that will accept an integer as its value.
The field description should be unified across all documents.
The field authors should be unified across all documents.
To complete this task, complete the following steps:

Modify the following schemas to incorporate the changes stated above:

These directions are extremely misleading… When you say “across all documents” one would assume that all referenced documents need to have that field. (This originally was interpreted as all documents… Including sub documents)

With the above directions and the ability to pull fields into the common document across all documents, there is no need for the book format… This is where I get confused. Based on what I want to do with the document, the format field will not have a value of book… This value does not need to be programmed as it would be the common portion (there is no book nesting). The only requirements for the format field that would contain a nested document for ebook and for audiobook.

Ok… I just read the instructions again and I now see the formats field differently… I now read it to state that if needed, this field will be used across all documents… Having used this mentality, I now changed the schema to the below:

[
    {   "_id":"<objectId>",
        "product_id": "<int>",
        "title": "<string>",
        "description": "<string>",
        "authors": ["<string>"],
        "catalogues":  
            {
                "isbn10": "<string>",
                "isbn13": "<string>"
            },
        "publisher": "<string>",
        "language": "<string>",
        "pages": "<int>",
        
        "format": [{
                     "ebook":
                        {
                            "epub": 
                                {
                                    "pages": "<int>"
                                },
                            "pdf": 
                                {
                                    "pages": "<int>"
                                }
                                
                        },
                     "audiobook":
                        {
                            "narrator": "<string>",
                            
                            
                            "length_minutes": "<int>"

                        }
                    }
                ]
    }
]

It still fails validation. I have moved almost all fields out of the ebook and audio book into the common field. However, with what I understand and see the pages of the ebook are different than that of the book… so I listed them under format.

The audio book is all contained in the common portion with the exception of the length in minutes field and narrator. These two fields are unique to the audio book portion. (you could argue that “author” is also since it is a one person field… But this is spitting hairs.

It still fails validation… I am running out of ideas… The format field is contained across all documents (common, ebook, and audiobook). The product_id field doesn’t need to change based on format in order to satisfy the requirement if embedded docs are used. And the description and authors fields are unified across all documents…

So… Don’t know what is wrong if all I get with the --verbose key is “document fails validation”… Any guidance or link to read that would clue me into my error would be appreciated… Below is the result of running the validation script on this lab.

PS D:\65945\m320> ./validate_m320 pattern_polymorphic --file pattern_polymorphic.json --verbose
Answer Filename: D:/65945/m320/pattern_polymorphic.json

Processing document: 1

  ... against solution: 1
The document fails validation.

Errors:
At least one of your solutions is not passing validation.

Thank you for your help Eoin, But I need some more information…

I am fully aware that there are multiple solutions, but that the most simplistic is what is programed into the solution. I also understand that this is going to be an exact science since it is running an automated validation. (there are no variants programed into the solution) So…

Logic would dictate that the solution should track the requirements that are given in the lab right? If so… then the solution (while there are many) should look for the field “formats”, “product_id”, “description” and “authors” right?

We will make the following modifications to our current schemas to have all documents share some common elements:

Across all documents, we will use a new field called format that will have a value of book, ebook, or audiobook.
Across all documents, we will have a field called product_id that will accept an integer as its value.
The field description should be unified across all documents.
The field authors should be unified across all documents.
To complete this task, complete the following steps:

Modify the following schemas to incorporate the changes stated above:

If I am supposed to program the solution this way, then I HAVE to have the above fields right? I need an answer on this before I continue… I am at a loss since I can get no indication as to what fails in my solution. Here is my solution:

[
    {   "_id":"<objectId>",
        "product_id": "<int>",
        "title": "<string>",
        "description": "<string>",
        "authors": ["<string>"],
        "catalogues":  
            {
                "isbn10": "<string>",
                "isbn13": "<string>"
            },
        "publisher": "<string>",
        "language": "<string>",
        "pages": "<int>",
        
        "eformats": [
                    {
                        "epub": 
                            {
                                "product_id": "<int>",     
                                "pages": "<int>"
                            },
                        "pdf": 
                            {
                                "product_id": "<int>",
                                "pages": "<int>"
                            },
                        "audio":
                            {
                                "product_id": "<int>",
                                "narrator": "<string>",
                                "length_minutes": "<int>"
                            }
                    }
                    ]
    }
]

According to my correspondence above, this should pass… But it doesn’t. I have no idea as to why.

The format field has been changed to eformats according to the advise above… If product_id is supposed to be across all documents, I added it to the different formats to enable tracking and reference the common fields (it should stay the same across the different formats). I have left the pages for “epub” and “pdf” alone since they can be unique. “audio” has the “narrator” and “length_minutes” field since this is unique to this format…

It fails validation…

PS D:\65945\m320> ./validate_m320 pattern_polymorphic --file pattern_polymorphic.json --verbose
Answer Filename: D:/65945/m320/pattern_polymorphic.json

Processing document: 1

  ... against solution: 1
The document fails validation.

Errors:
At least one of your solutions is not passing validation.

I have no idea where I can go from here… And I am really confused since mongo stresses that data duplication is ok (not ideal, but ok)… I have watched the polymorphic video 10 times and while it is a good video, it doesn’t clearly go over how to go about combining the different documents into a single view.

It would be great to see this in action to understand the process. (watch the lecturer modify an actual schema)

Hi @David_44057

Rather than continue this in the thread, I’ve sent you a message directly. Essentially, the secret to success for this validator is to use three different schemas, one for traditional books, one for electronic formats and one for audio books.

The ability of MongoDB to have multiple parallel schemas within a given collection gives it great flexibility in terms of schema design so each schema can be simplified to only the fields required for the distinct item, say audio books for example.

I’m just noting this here for others who might read the thread later, we can discuss this in more depth in 1:1 messages.

Kindest regards,
Eoin

May be, just may be:

Yet, you named your new field

in your last post. May be it is just typing inattention.

In your one post, where the new field was correctly named format. You were missing book as a possible value.

Is this a private message? Or am I still on the message board? Before I go into anything else I want to ensure that this is private so I don’t confuse anyone else.

Hi @David_44057

The message you asked about is publically visible, if you select the ‘mail’ / ‘letter’ icon you can send a private message.

Hope this helps!
Eoin