Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From SQL to NoSQL: A Gentle Introduction For Developers

From SQL to NoSQL: A Gentle Introduction For Developers

When you need to model data, is your first instinct to start breaking it down into rows and columns? Mine used to be too. When you want to develop apps in a modern, agile way, NoSQL databases can be the best option. Come to this talk to learn how to take advantage of all that NoSQL databases have to offer and discover the benefits of changing your mindset from the legacy, tabular way of modeling data. We’ll compare and contrast the terms and concepts in SQL databases and MongoDB, explain the benefits of using MongoDB compared to SQL databases, and walk through data modeling basics so you feel confident as you begin using MongoDB.

Joe Karlsson

October 19, 2019
Tweet

More Decks by Joe Karlsson

Other Decks in Programming

Transcript

  1. Did you know that the two main bottlenecks for web

    app performance are: @JoeKarlsson1 Source: https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4 * Network speed * Database execution speed
  2. We can only control one of these things @JoeKarlsson1 Source:

    https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4
  3. { name: “Joe Karlsson”, company: “MongoDB”, title: [ “Developer Advocate”,

    “Software Engineer” ], twitter: “@JoeKarlsson1”, website: “joekarlsson.com”, }
  4. Agenda 1.Map terms & concepts from SQL to MongoDB 2.Discover

    the 4 humongous advantages of MongoDB 3.Change your mindset in 3 key ways @JoeKarlsson1
  5. Agenda 1.Map terms & concepts from SQL to MongoDB 2.Discover

    the 4 humongous advantages of MongoDB 3.Change your mindset in 3 key ways @JoeKarlsson1 Row Column Table Database Index Join Join Left Outer Join Recursive Common Table Expressions View Transaction Document Field Collection Database Index Embedding Database References $lookup $graphLookup View Transaction
  6. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  7. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  8. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  9. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  10. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  11. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  12. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  13. @JoeKarlsson1 MongoDB stores data in documents { first_name: "Paul", surname:

    "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  14. @JoeKarlsson1 Modeling data in MongoDB vs SQL { first_name: "Paul",

    surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] }
  15. @JoeKarlsson1 Modeling data in MongoDB vs SQL { first_name: "Paul",

    surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } ID first_name surname cell city location_x location_y 1 Paul Miller 447557505611 London 45.123 47.232 Users
  16. @JoeKarlsson1 Modeling data in MongoDB vs SQL { first_name: "Paul",

    surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } ID user_id profession 10 1 banking 11 1 finance 12 1 trader Professions ID first_name surname cell city location_x location_y 1 Paul Miller 447557505611 London 45.123 47.232 Users
  17. @JoeKarlsson1 Modeling data in MongoDB vs SQL { first_name: "Paul",

    surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } ID user_id model year 20 1 Bentley 1973 21 1 Rolls Royce 1965 Cars ID user_id profession 10 1 banking 11 1 finance 12 1 trader Professions ID first_name surname cell city location_x location_y 1 Paul Miller 447557505611 London 45.123 47.232 Users
  18. @JoeKarlsson1 Modeling data in MongoDB vs SQL { first_name: "Paul",

    surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } ID user_id model year 20 1 Bentley 1973 21 1 Rolls Royce 1965 Cars ID user_id profession 10 1 banking 11 1 finance 12 1 trader Professions ID first_name surname cell city location_x location_y 1 Paul Miller 447557505611 London 45.123 47.232 Users
  19. @JoeKarlsson1 Collections vs Tables { first_name: "Paul", surname: "Miller", cell:

    "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } { first_name: ”Joe", surname: ”Karlsson", cell: ”1235552222", city: ”Minneapolis”, profession: [”software engineer", ”developer advocate"], } { first_name: ”BMO", surname: ”Karlsson", city: ”Minneapolis", } Users Users ID first_name surname cell city location_ x location_y 1 Paul Miller 447557505611 London 45.123 47.232 2 Joe Karlsson 1235552222 Minneapolis NULL NULL 3 Sydney Schaefer NULL Minneapolis NULL NULL
  20. @JoeKarlsson1 Collections vs Tables { first_name: "Paul", surname: "Miller", cell:

    "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } { first_name: ”Joe", surname: ”Karlsson", cell: ”1235552222", city: ”Minneapolis”, profession: [”software engineer", ”developer advocate"], } { first_name: ”BMO", surname: ”Karlsson", city: ”Minneapolis", } Users Users ID first_name surname cell city location_ x location_y 1 Paul Miller 447557505611 London 45.123 47.232 2 Joe Karlsson 1235552222 Minneapolis NULL NULL 3 BMO Karlsson NULL Minneapolis NULL NULL
  21. @JoeKarlsson1 Collections vs Tables { first_name: "Paul", surname: "Miller", cell:

    "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } { first_name: ”Joe", surname: ”Karlsson", cell: ”1235552222", city: ”Minneapolis”, profession: [”software engineer", ”developer advocate"], } { first_name: ”BMO", surname: ”Karlsson", city: ”Minneapolis", } Users Users ID first_name surname cell city location_ x location_y 1 Paul Miller 447557505611 London 45.123 47.232 2 Joe Karlsson 1235552222 Minneapolis NULL NULL 3 BMO Karlsson NULL Minneapolis NULL NULL
  22. Document Row(s) ID a ... 1 b ... 2 ...

    ... 3 ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... { ...
 a: “b”
 ... }
  23. Field ID a ... 1 b ... 2 c ...

    3 ... ... { ...
 a: “b”
 ... } { ...
 a: “c”
 ... } Column
  24. Table Collection { ... } ... ... ... ... ...

    ... ... ... ... ... ... ... { ... } { ... }
  25. @JoeKarlsson1 So a DBA walks
 into a NoSQL bar… But

    immediately leaves because they couldn’t find table.
  26. Database Database ... ... ... ... ... ... ... ...

    ... ... ... ... { ... } { ... } { ... } { ... } { ... } { ... } { ... } ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
  27. Index Index { ... } { ... } { ...

    } { ... } ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
  28. View View { ... } ... ... ... ... ...

    ... ... ... ... ... ... ... { ... } { ... }
  29. Embedding { ...
 a: “b”,
 ... c: {
 d: “e”


    ...
 },
 ... } ID a ... 1 b ... 2 ... ... 3 ... ... ... d ... 1 e ... ... ... ... Join
  30. Join Database References ID ... ... 1 ... ... 2

    ... ... 3 ... ... ... ... ... 1 ... ... ... ... ... { ... } { ... } { ... } { ... } { ... } { ... } { ... }
  31. Multi-Record ACID Transaction Multi-Document ACID Transaction { ... } {

    ... } { ... } { ... } { ... } { ... } { ... } ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
  32. @JoeKarlsson1 Row Column Table Database Index Join Join Left Outer

    Join Recursive Common Table Expressions View Transaction Document Field Collection Database Index Embedding Database References $lookup $graphLookup View Transaction The journey from SQL to MongoDB 1) Map terms & concepts from SQL to MongoDB
  33. Agenda 1.Map terms & concepts from SQL to MongoDB 2.Discover

    the 4 humongous advantages of MongoDB 3.Change your mindset in 3 key ways @JoeKarlsson1 1.Program faster 2.Pivot easier 3.Query faster 4.Scale Cheaper
  34. @JoeKarlsson1 Program faster! { first_name: "Paul", surname: "Miller", cell: "447557505611",

    city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], } ID first_name surname cell city location_x location_y 1 Paul Miller 447557505611 London 45.123 47.232 Users ID user_id profession 10 1 banking 11 1 finance 12 1 trader Professions
  35. import pymongo
 from pymongo import MongoClient # CONNECT TO THE

    DB client = MongoClient() client =
 pymongo.MongoClient("mongodb+srv://
 username:password@cluster0nsdia.
 mongodb.net/test?retryWrites=true") db = client.fabapp 
 # THE ID OF THE USER WHOSE PROFILE WE WILL BE RETRIEVING AND UPDATING userId = 1 Program faster! import mysql.connector 
 # CONNECT TO THE DB mydb = mysql.connector.connect(
 host="localhost",
 user=”username",
 passwd=”password",
 database=”fabapp”
 ) mycursor = mydb.cursor() 
 # THE ID OF THE USER WHOSE PROFILE WE WILL BE RETRIEVING AND UPDATING userId = 1
  36. # GET THE USER'S PROFILE INFORMATION ### Pull the info

    from the Users table & put it in the user dictionary sql = "Select * FROM Users WHERE Users.ID=%s”
 values = (userId,)
 mycursor.execute(sql, values)
 result = mycursor.fetchone() user = {
 "first_name": result[1],
 "surname": result[2],
 "cell": result[3],
 "city": result[4],
 "location_x": result[5],
 "location_y": result[6]
 } # GET THE USER'S PROFILE INFORMATION ## We can pull all of the info from the same document since we used embedding user = db['Users'].find_one({"_id": userId}) Program faster! ### Pull the info from the Professions table & put it in the user dictionary sql = "Select * FROM Professions WHERE
 Professions.user_id=%s”
 values = (userId,)
 mycursor.execute(sql, values)
 results = mycursor.fetchall() professions = []
 for result in results:
 professions.append(result[2])
 user["professions"] = professions
  37. # UPDATE THE USER DICTIONARY BASED ON USER INPUT IN

    THE APP ### We'll update the user dictionary manually for simplicity user = {
 "first_name": "NewFirst",
 "surname": "NewSurname",
 "cell": "123-456-7890",
 "city": "NewCity",
 "location": [40.762, -73.979],
 "professions": [”Manager", "Engineer"]
 } Program faster! # UPDATE THE USER DICTIONARY BASED ON USER INPUT IN THE APP ### We'll update the user dictionary manually for simplicity user = {
 "first_name": "NewFirst",
 "surname": "NewSurname",
 "cell": "123-456-7890",
 "city": "NewCity",
 "location_x": 40.762, 
 "location_y": 73.979,
 "professions": [”Manager", "Engineer"]
 }
  38. # UPDATE THE USER'S PROFILE IN THE DATABASE ### First

    update what is stored in the Users table sql = "UPDATE Users SET first_name=%s, surname=%s, cell=%s, city=%s, location_x=%s, location_y=%s WHERE (ID=%s)"
 values = (
 user["first_name"], 
 user["surname"], 
 user["cell"], 
 user["city"], 
 user["location_x"], 
 user["location_y"], 
 userId)
 mycursor.execute(sql, values) mydb.commit() # UPDATE THE USER'S PROFILE IN THE DATABASE ### Since the user's data is stored in a single document, we only have to make one update result = db['Users'].update_one(
 {"_id": userId}, {"$set": user}) 
 Program faster! ### Delete existing records in Professions table and add new ones sql = "DELETE FROM Professions WHERE user_id=%s”
 values = (userId,)
 mycursor.execute(sql, values)
 mydb.commit() if(len(user["professions"]) > 0):
 sql = "INSERT INTO Professions 
 (user_id,profession) VALUES (%s, %s)”
 values = []
 for profession in user["professions"]:
 values.append((userId, profession))
 mycursor.executemany(sql,values)
 mydb.commit()
  39. @JoeKarlsson1 Pivot easier! Easily change the shape of your data

    as your app evolves. SQL MongoDB {
 a: “b”,
 c: “one”,
 e: “f” } {
 a: “b”,
 c: 1,
 new: “no biggee” } ALTER TABLE `mydb`.`letters_table` DROP COLUMN `e`, ADD COLUMN `New` VARCHAR(45) NULL AFTER `C`, CHANGE COLUMN `C` `C` INT NULL DEFAULT NULL ;
  40. @JoeKarlsson1 Query faster! Stop doing expensive joins to get your

    data. SQL MongoDB ID a ... 1 b ... 2 ... ... 3 ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... { ...
 a: “b”,
 ... c: {
 d: “e”
 ...
 },
 ... }
  41. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB
  42. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 1. Program faster # UPDATE THE USER'S PROFILE IN THE DATABASE ### First update what is stored in the Users table sql = "UPDATE Users SET first_name=%s, surname=%s, cell=%s, city=%s, location_x=%s, location_y=%s WHERE (ID=%s)"
 values = (
 user["first_name"], 
 user["surname"], 
 user["cell"], 
 user["city"], 
 user["location_x"], 
 user["location_y"], 
 userId)
 mycursor.execute(sql, values) mydb.commit() # UPDATE THE USER'S PROFILE IN THE DATABASE ### Since the user's data is stored in a single document, we only have to make one update result = db['Users'].update_one(
 {"_id": userId}, {"$set": user}) 

  43. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 2. Scale cheaper 1. Program faster
  44. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 3. Query faster 2. Scale cheaper 1. Program faster
  45. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 4. Pivot easier 3. Query faster 2. Scale cheaper 1. Program faster
  46. Agenda 1.Map terms & concepts from SQL to MongoDB 2.Discover

    the 4 humongous advantages of MongoDB 3.Change your mindset in 3 key ways @JoeKarlsson1 1.Not all documents in a collection need to have the same fields. 2.Data that is accessed together should be stored together. 3.Stop using transactions regularly.
  47. @JoeKarlsson1 Not all documents in a collection need to have

    the same fields. The Polymorphic Pattern { first_name: "Paul", surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } { first_name: ”Joe", surname: ”Karlsson", cell: ”1235552222", city: ”Minneapolis”, profession: [”software engineer", ”developer advocate"], } { first_name: ”BMO", surname: ”Karlsson", city: ”Minneapolis", }
  48. @JoeKarlsson1 Not all documents in a collection need to have

    the same fields. The Outlier Pattern { _id: ”JoeKarlsson1", displayName: ”JoeKarlsson1”, 
 numFollowers: 2095 followers: [
 “jessicaewest”,
 “wesley83”, 
 “GraceFr”
 ... ] } { _id: ”KimKardashian", displayName: ”Kim Kardashian West", 
 numFollowers: 62104245 followers: [
 “c_hotaling”,
 “IAmJerdog”, 
 “ChloeCondon”
 ... ], has_extras: true { _id: ”KimKardashian_1", twitter_id: “KimKardashian”,
 is_overflow: true, followers: [
 “StephenAtHome”,
 “TheEllenShow”, 
 “hulu”
 ... ] }
  49. @JoeKarlsson1 Storage vs Developer Costs 0 25000 50000 75000 100000

    1985 2017 Storage Cost per GB Developer Salary Data that is accessed together should be stored together.
  50. @JoeKarlsson1 Data that is accessed together should be stored together.

    Don’t normalize your data for the sake of normalizing it. {
 a: “b”, c: {
 d: “e”
 ...
 }, f: [“g”, “h”, “i”], j: [ 
 { k: “l” }, 
 { m: “n” } ] }
  51. @JoeKarlsson1 Stop using transactions regularly. Relying on transactions is a

    bad design smell. { ... } { ... } { ... } { ... } { ... } { ... } { ... }
  52. @JoeKarlsson1 Stop using transactions regularly. Relying on transactions is a

    bad design smell. { ... } { ... } { ... } { ... } { ... } { ... } { ... }
  53. @JoeKarlsson1 Row Column Table Database Index Join Join Left Outer

    Join Recursive Common Table Expressions View Transaction Document Field Collection Database Index Embedding Database References $lookup $graphLookup View Transaction The journey from SQL to MongoDB 1) Map terms & concepts from SQL to MongoDB
  54. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB
  55. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 1. Program faster # UPDATE THE USER'S PROFILE IN THE DATABASE ### First update what is stored in the Users table sql = "UPDATE Users SET first_name=%s, surname=%s, cell=%s, city=%s, location_x=%s, location_y=%s WHERE (ID=%s)"
 values = (
 user["first_name"], 
 user["surname"], 
 user["cell"], 
 user["city"], 
 user["location_x"], 
 user["location_y"], 
 userId)
 mycursor.execute(sql, values) mydb.commit() # UPDATE THE USER'S PROFILE IN THE DATABASE ### Since the user's data is stored in a single document, we only have to make one update result = db['Users'].update_one(
 {"_id": userId}, {"$set": user}) 

  56. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 2. Scale cheaper 1. Program faster
  57. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 3. Query faster 2. Scale cheaper 1. Program faster
  58. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 4. Pivot easier 3. Query faster 2. Scale cheaper 1. Program faster
  59. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 3) Change your mindset in 3 key ways
  60. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 3) Change your mindset in 3 key ways 1. Not all documents in a collection need to have the same fields. { first_name: "Paul", surname: "Miller", cell: "447557505611", city: "London", location: [45.123,47.232], profession: ["banking", "finance", "trader"], cars: [ { model: "Bentley", year: 1973 }, { model: "Rolls Royce", year: 1965 } ] } { first_name: ”Joe", surname: ”Karlsson", cell: ”1235552222", city: ”Minneapolis”, profession: [”software engineer", ”developer advocate"], } { first_name: ”BMO", surname: ”Karlsson", city: ”Minneapolis", }
  61. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 3) Change your mindset in 3 key ways 1. Not all documents in a collection need to have the same fields. 2. Data that is accessed together should be stored together. {
 a: “b”, c: {
 d: “e”
 ...
 }, f: [“g”, “h”, “i”], j: [ 
 { k: “l” }, 
 { m: “n” } ] }
  62. @JoeKarlsson1 The journey from SQL to MongoDB 1) Map terms

    & concepts from SQL to MongoDB 2) Discover the 4 humongous advantages of MongoDB 3) Change your mindset in 3 key ways 1. Not all documents in a collection need to have the same fields. 2. Data that is accessed together should be stored together. 3. Stop using transactions regularly. { ... } { ... } { ... } { ... } { ... } { ... } { ... }
  63. { name: “Joe Karlsson”, company: “MongoDB”, title: [ “Developer Advocate”,

    “Software Engineer” ], twitter: “@JoeKarlsson1”, website: “joekarlsson.com”, }
  64. Additional Resources •http://bit.ly/MongoDBChicago2019 •$200 in free Atlas credits • Advanced

    Schema Design Patterns (webinar) • Building with Patterns: A Summary (blog series) • M320: Data Modeling (MongoDB University Course) @JoeKarlsson1
  65. Additional Resources @JoeKarlsson1 • The MongoDB Docs • JSON Schema

    Validation – Locking down your model the smart way • JSON Schema Validation - Checking Your Arrays • M121: The MongoDB Aggregation Framework