Baseret på dine krav til din software kan du prioritere fleksibilitet, skalerbarhed, ydeevne eller hastighed. Derfor er udviklere og virksomheder ofte forvirrede, når de vælger en database til deres behov. Hvis du har brug for en database, der giver høj fleksibilitet og skalerbarhed og dataaggregation til kundeanalyser, kan MongoDB være det rigtige valg for dig!

I denne artikel vil vi diskutere strukturen af MongoDB-databasen, og hvordan du opretter, overvåger og administrerer din database! Lad os komme i gang.

Hvordan er en MongoDB-database opbygget?

MongoDB er en skemaløs NoSQL-database. Det betyder, at du ikke angiver en struktur for tabellerne/databaserne, som du gør for SQL-databaser.

Vidste du, at NoSQL-databaser faktisk er hurtigere end relationelle databaser? Dette skyldes egenskaber som indeksering, sharding og aggregeringspipelines. MongoDB er også kendt for sin hurtige udførelse af forespørgsler. Det er derfor, at den foretrækkes af virksomheder som Google, Toyota og Forbes.

Nedenfor vil vi undersøge nogle af de vigtigste egenskaber ved MongoDB.

Dokumenter

MongoDB har en dokumentdatamodel, der gemmer data som JSON-dokumenter. Dokumenterne mapper naturligt til objekterne i applikationskoden, hvilket gør det mere ligetil for udviklere at bruge.

I en tabel i en relationel database skal du tilføje en kolonne for at tilføje et nyt felt. Det er ikke tilfældet med felter i et JSON-dokument. Felter i et JSON-dokument kan variere fra dokument til dokument, så de vil ikke blive tilføjet til hver enkelt post i databasen.

Dokumenter kan lagre strukturer som f.eks. arrays, der kan indlejres i hinanden for at udtrykke hierarkiske relationer. Derudover konverterer MongoDB dokumenter til en binær JSON-type (BSON). Dette sikrer hurtigere adgang og øget understøttelse af forskellige datatyper som streng, heltal, boolsk tal og meget mere!

Replika-sæt

Når du opretter en ny database i MongoDB, opretter systemet automatisk mindst 2 yderligere kopier af dine data. Disse kopier er kendt som “replikasæt”, og de replikerer løbende data mellem dem, hvilket sikrer en forbedret tilgængelighed af dine data. De giver også beskyttelse mod nedetid under en systemfejl eller planlagt vedligeholdelse.

Samlinger

En samling er en gruppe af dokumenter, der er tilknyttet en database. De svarer til tabeller i relationelle databaser.

Samlinger er dog meget mere fleksible. For det første er de ikke afhængige af et skema. For det andet behøver dokumenterne ikke at være af samme datatype!

Du kan få vist en liste over de samlinger, der hører til en database, ved at bruge kommandoen listCollections.

Aggregeringspipelines

Du kan bruge denne ramme til at klubbe flere operatorer og udtryk. Den er fleksibel, fordi den giver dig mulighed for at behandle, transformere og analysere data af enhver struktur.

På grund af dette tillader MongoDB hurtige datastrømme og funktioner på tværs af 150 operatører og udtryk. Den har også flere faser, som f.eks. union-fasen, der fleksibelt sætter resultater fra flere samlinger sammen.

Indekser

Du kan indeksere ethvert felt i et MongoDB-dokument for at øge dets effektivitet og forbedre forespørgselshastigheden. Indeksering sparer tid ved at scanne indekset for at begrænse de inspicerede dokumenter. Er det ikke langt bedre end at læse hvert dokument i samlingen?

Du kan bruge forskellige indekseringsstrategier, herunder sammensatte indekser på flere felter. Lad os f.eks. sige, at du har flere dokumenter, der indeholder medarbejderens for- og efternavn i separate felter. Hvis du ønsker at få for- og efternavnet returneret, kan du oprette et indeks, der indeholder både “Last name” og “First name”. Dette ville være meget bedre end at have et indeks på “Last name” og et andet på “First name”.

Du kan bruge værktøjer som Performance Advisor til at forstå yderligere, hvilke forespørgsler der kan drage fordel af indekser.

Sharding

Sharding fordeler et enkelt datasæt på flere databaser. Datasættet kan derefter gemmes på flere maskiner for at øge den samlede lagerkapacitet i et system. Dette skyldes, at det opdeler større datasæt i mindre stykker og gemmer dem i forskellige dataknudepunkter.

MongoDB deler data på samlingsniveau og fordeler dokumenterne i en samling på tværs af shards i en klynge. Dette sikrer skalerbarhed ved at gøre det muligt for arkitekturen at håndtere de største applikationer.

Sådan oprettes en MongoDB-database

Du skal først installere den rigtige MongoDB-pakke, der passer til dit operativsystem. Gå til siden ‘Download MongoDB Community Server‘. Vælg den seneste “version”, “pakkeformat” som zip-fil og “platform” som dit OS blandt de tilgængelige muligheder, og klik på “Download” som vist nedenfor:

Dette billede viser de tilgængelige muligheder - Version, Platform og Pakke under download af MongoDB Community Server.
MongoDB community server download process. (Billedkilde: MongoDB Community Server)

Processen er ret ligetil, så du vil have MongoDB installeret i dit system på ingen tid!

Når du har gennemført installationen, skal du åbne din kommandoprompt og skrive mongod -version for at bekræfte den. Hvis du ikke får følgende output og i stedet ser en række fejl, skal du muligvis geninstallere den:

Dette er et kodestykke til at kontrollere MongoDB-versionen efter installationen.
Kontrollere MongoDB version. (Billedkilde: configserverfirewall)

Brug af MongoDB Shell

Før vi går i gang, skal du sikre dig, at:

  • Din klient har Transport Layer Security og er på din IP-tilladelsesliste.
  • Du har en brugerkonto og et password på den ønskede MongoDB-klynge.
  • Du har installeret MongoDB på din enhed.

Trin 1: Adgang til MongoDB Shell

Start MongoDB-serveren ved at følge instruktionerne for hvert OS. For Windows skal du skrive følgende kommando. For andre operativsystemer henvises til MongoDB-dokumentationen.

net start MongoDB

Dette bør give følgende output:

Dette er et kodestykke til at initialisere MongoDB-serveren
Kører MongoDB server. (Billedkilde: c-sharpcorner)

Den foregående kommando initialiserede MongoDB-serveren. For at køre den skal vi indtaste mongo i kommandoprompten.

Dette er et kodestykke til at køre MongoDB-serveren.
Kører MongoDB shell. (Billedkilde: bmc)

Her i MongoDB-shellen kan vi udføre kommandoer til at oprette databaser, indsætte data, redigere data, udstede administrative kommandoer og slette data.

Trin 2: Opret din database

I modsætning til almindelige relationelle databaser har MongoDB ikke en kommando til oprettelse af database. I stedet er der et nøgleord kaldet use, som skifter til en specificeret database. Hvis databasen ikke findes, oprettes der en ny database, ellers linkes der til den eksisterende database.

For eksempel, for at igangsætte en database kaldet “company”, skal du indtaste:

use Company
Dette er et kodestykke til at oprette en database i MongoDB.
Oprettelse af database i MongoDB.

Du kan skrive db for at bekræfte den database, du lige har oprettet i dit system. Hvis den nye database, du har oprettet, vises, har du oprettet forbindelse til den med succes.

Hvis du vil tjekke de eksisterende databaser, skal du skrive show dbs, og det vil give dig alle databaserne i dit system:

Dette er et kodestykke til at se de eksisterende databaser i systemet.
Visning af databaser i MongoDB.

Ved installation af MongoDB oprettes som standard admin-, config- og lokale databaser.

Har du bemærket, at den database, vi har oprettet, ikke vises? Det er fordi vi ikke har gemt værdier i databasen endnu! Vi vil diskutere indsættelse under afsnittet om databaseadministration.

Brug af Atlas UI

Du kan også komme i gang med MongoDB’s databasetjeneste, Atlas. Selv om du muligvis skal betale for at få adgang til nogle funktioner i Atlas, er de fleste databasefunktionaliteter tilgængelige med det gratis niveau. Funktionerne i det gratis niveau er mere end nok til at oprette en MongoDB-database.

Før vi går i gang, skal du sikre dig, at:

  1. Din IP er på tilladelseslisten.
  2. Du har en brugerkonto og et password på den ønskede MongoDB-klynge.

For at oprette en MongoDB-database med AtlasUI skal du åbne et browservindue og logge ind på https://cloud.mongodb.com. Fra din klyngeside skal du klikke på Browse Collections (Gennemse samlinger). Hvis der ikke er nogen databaser i klyngen, kan du oprette din database ved at klikke på knappen Add My Own Data (Tilføj mine egne data).

Prompten vil bede dig om at angive et database- og samlingsnavn. Når du har givet dem navne, skal du klikke på Opret, og så er du færdig! Du kan nu indtaste nye dokumenter eller oprette forbindelse til databasen ved hjælp af drivere.

Administration af din MongoDB-database

I dette afsnit gennemgår vi et par smarte måder at administrere din MongoDB-database effektivt på. Du kan gøre dette ved enten at bruge MongoDB-kompasset eller gennem samlinger.

Brug af samlinger

Mens relationelle databaser besidder veldefinerede tabeller med specificerede datatyper og kolonner, har NoSQL samlinger i stedet for tabeller. Disse samlinger har ingen struktur, og dokumenter kan variere – du kan have forskellige datatyper og felter uden at skulle matche et andet dokuments format i samme samling.

Lad os for at demonstrere dette oprette en samling kaldet “Employee” og tilføje et dokument til den:

db.Employee.insert(
  {
   	"Employeename" : "Chris",
   	"EmployeeDepartment" : "Sales"
  }
)

Hvis indsættelsen er vellykket, returneres WriteResult({ "nInserted" : 1 }):

Dette kodestykke returnerer WriteResult({
Succesfuld indsættelse i MongoDB.

Her henviser “db” til den aktuelt tilsluttede database. “Employee” er den nyligt oprettede samling på virksomhedsdatabasen.

Vi har ikke indstillet en primær nøgle her, fordi MongoDB automatisk opretter et primærnøglefelt kaldet “_id” og indstiller en standardværdi til det.

Kør nedenstående kommando for at tjekke samlingen i JSON-format:

db.Employee.find().forEach(printjson)

Output:

{
  "_id" : ObjectId("63151427a4dd187757d135b8"),
  "Employeename" : "Chris",
  "EmployeeDepartment" : "Sales"
}

Du kan ændre værdien af standard primærnøglen, mens “_id”-værdien tildeles automatisk. Denne gang indsætter vi et andet dokument i databasen “Employee” med værdien “_id” som “1”:

db.Employee.insert(
  {  
   	"_id" : 1,
   	"EmployeeName" : "Ava",
   	"EmployeeDepartment" : "Public Relations"
  }
)

Ved at køre kommandoen db.Employee.find().forEach(printjson) får vi følgende output:

Outputtet viser dokumenterne i medarbejdersamlingen sammen med deres primære nøgle
Dokumenter i samlingen med deres primære nøgle.

I ovenstående output er “_id”-værdien for “Ava” sat til “1” i stedet for at blive tildelt en værdi automatisk.

Nu, hvor vi har tilføjet værdier til databasen, kan vi kontrollere, om den vises under de eksisterende databaser i vores system ved hjælp af følgende kommando:

show dbs
Outputtet viser medarbejdersamlingen i de eksisterende databaser i vores system.
Visning af listen over databaser.

Og voila! Du har med succes oprettet en database i dit system!

Brug af MongoDB-kompasset

Selv om vi kan arbejde med MongoDB-servere fra Mongo-skallen, kan det nogle gange være kedeligt. Du kan opleve dette i et produktionsmiljø.

Der er dog et kompasværktøj (med det passende navn Compass), der er skabt af MongoDB, som kan gøre det nemmere. Det har en bedre GUI og tilføjede funktionaliteter som datavisualisering, præstationsprofilering og CRUD-adgang (create, read, update, delete) til data, databaser og samlinger.

Du kan downloade Compass IDE til dit operativsystem og installere det med dets enkle proces.

Derefter skal du åbne programmet og oprette en forbindelse med serveren ved at indsætte forbindelsesstrengen. Hvis du ikke kan finde den, kan du klikke på Fill in connection fields individually (Udfyld forbindelsesfelter individuelt). Hvis du ikke ændrede portnummeret, mens du installerede MongoDB, skal du blot klikke på forbindelsesknappen, og så er du inde! Ellers skal du blot indtaste de værdier, du har indstillet, og klikke på Connect (Forbind).

Dette billede viser vinduet Ny forbindelse, hvor du kan vælge at indsætte forbindelses-url'en.
vinduet Ny forbindelse i MongoDB.. (Image source: mongodb)

Derefter skal du angive værtsnavn, port og godkendelse i vinduet Ny forbindelse.

I MongoDB Compass kan du oprette en database og tilføje dens første samling samtidig. Sådan gør du det:

  1. Klik på Create database for at åbne prompten.
  2. Indtast navnet på databasen og dens første samling.
  3. Klik på Create database.

Du kan indsætte flere dokumenter i din database ved at klikke på databasens navn og derefter klikke på samlingens navn for at se fanen Documents. Du kan derefter klikke på knappen Add data for at indsætte et eller flere dokumenter i din samling.

Når du tilføjer dine dokumenter, kan du indtaste dem et ad gangen eller som flere dokumenter i et array. Hvis du tilføjer flere dokumenter, skal du sikre, at disse kommaseparerede dokumenter er omsluttet af firkantede parenteser. For eksempel:

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] },
{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] },
{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] },
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] },
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] },
{ _id: 6, item: { name: "strawberry", code: "123" }, tags: [ "B" ] }

Klik til sidst på Insert for at tilføje dokumenterne til din samling. Sådan ser et dokumentets krop ud:

{
  "StudentID" : 1
  "StudentName" : "JohnDoe"
}

Her er feltnavnene “StudentID” og “StudentName”. Feltværdierne er henholdsvis “1” og “JohnDoe”.

Nyttige kommandoer

Du kan administrere disse samlinger ved hjælp af kommandoer til rolleadministration og brugeradministration.

Kommandoer til brugeradministration

MongoDB-brugerstyringskommandoer indeholder kommandoer, der vedrører brugeren. Vi kan oprette, opdatere og slette brugerne ved hjælp af disse kommandoer.

dropUser

Denne kommando fjerner en enkelt bruger fra den angivne database. Nedenfor er syntaksen:

db.dropUser(username, writeConcern)

Her er username et obligatorisk felt, der angiver navnet på den bruger, der skal fjernes fra databasen. Det valgfri felt writeConcern indeholder niveauet af skrivebekymring for fjernelsesoperationen. Skriveinteressen kan bestemmes ved hjælp af det valgfrie felt writeConcern.

Før du sletter en bruger, der har rollen userAdminAnyDatabase, skal du sikre dig, at der er mindst én anden bruger med brugeradministrationsrettigheder.

I dette eksempel dropper vi brugeren “user26” i testdatabasen:

use test
db.dropUser("user26", {w: "majority", wtimeout: 4000})

Output:

> db.dropUser("user26", {w: "majority", wtimeout: 4000});
true
createUser

Denne kommando opretter en ny bruger til den angivne database på følgende måde:

db.createUser(user, writeConcern)

Her er user et obligatorisk felt, der indeholder dokumentet med autentifikations- og adgangsoplysninger om den bruger, der skal oprettes. Det valgfrie felt writeConcern indeholder niveauet for skriveinteresse for oprettelsesoperationen. Skriveinteressen kan bestemmes ved hjælp af det valgfrie felt writeConcern.

createUser returnerer en fejlmeddelelse om en dobbelt bruger, hvis brugeren allerede findes i databasen.

Du kan oprette en ny bruger i testdatabasen på følgende måde:

use test
db.createUser(
  {
    user: "user26",
    pwd: "myuser123",
    roles: [ "readWrite" ]  
  }
);

Du kan oprette en ny bruger på følgende måde: Du kan oprette en ny bruger på følgende måde: Output er som følger:

Successfully added user: { "user" : "user26", "roles" : [ "readWrite", "dbAdmin" ] }
grantRolesToUser

Du kan bruge denne kommando til at tildele yderligere roller til en bruger. Hvis du vil bruge den, skal du huske følgende syntaks:

db.runCommand(
  {
    grantRolesToUser: "<user>",
    roles: [ <roles> ],
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

Du kan angive både brugerdefinerede og indbyggede roller i de ovennævnte roller. Hvis du vil angive en rolle, der findes i den samme database, som grantRolesToUser kører, kan du enten angive rollen med et dokument, som nævnt nedenfor:

{ role: "<role>", db: "<database>" }

Eller du kan blot angive rollen med rollens navn. F.eks:

"readWrite"

Hvis du vil angive den rolle, der findes i en anden database, skal du angive rollen med et andet dokument.

Hvis du vil tildele en rolle i en database, skal du bruge handlingen grantRole i den angivne database.

Her er et eksempel for at give dig et klart billede. Tag f.eks. en bruger productUser00 i produktdatabasen med følgende roller:

"roles" : [
  {
    "role" : "assetsWriter",
    "db" : "assets"
  }
]

Operationen grantRolesToUser giver “productUser00” rollen readWrite i lagerdatabasen og rollen “read” i produktdatabasen:

use products
db.runCommand({
  grantRolesToUser: "productUser00",
  roles: [
    { role: "readWrite", db: "stock"},
    "read"
  ],
  writeConcern: { w: "majority" , wtimeout: 2000 }
})

Brugeren “productUser00” i produktdatabasen har nu følgende roller:

"roles" : [
  {
    "role" : "assetsWriter",
    "db" : "assets"
  },
  {
    "role" : "readWrite",
    "db" : "stock"
  },
  {
    "role" : "read",
    "db" : "products"
  }
]
usersInfo

Du kan bruge kommandoen usersInfo til at returnere oplysninger om en eller flere brugere. Her er syntaksen:

db.runCommand(
  {
    usersInfo: <various>,
    showCredentials: <Boolean>,
    showCustomData: <Boolean>,
    showPrivileges: <Boolean>,
    showAuthenticationRestrictions: <Boolean>,
    filter: <document>,
    comment: <any> 
  }
)
{ usersInfo: <various> }

Med hensyn til adgang kan brugere altid se deres egne oplysninger. For at se en anden brugers oplysninger skal den bruger, der kører kommandoen, have rettigheder, der omfatter viewUser-handlingen på den anden brugers database.

Når du kører kommandoen userInfo, kan du få følgende oplysninger afhængigt af de angivne indstillinger:

{
  "users" : [
    {
      "_id" : "<db>.<username>",
      "userId" : <UUID>, // Starting in MongoDB 4.0.9
      "user" : "<username>",
      "db" : "<db>",
      "mechanisms" : [ ... ],  // Starting in MongoDB 4.0
      "customData" : <document>,
      "roles" : [ ... ],
      "credentials": { ... }, // only if showCredentials: true
      "inheritedRoles" : [ ... ],  // only if showPrivileges: true or showAuthenticationRestrictions: true
      "inheritedPrivileges" : [ ... ], // only if showPrivileges: true or showAuthenticationRestrictions: true
      "inheritedAuthenticationRestrictions" : [ ] // only if showPrivileges: true or showAuthenticationRestrictions: true
      "authenticationRestrictions" : [ ... ] // only if showAuthenticationRestrictions: true
    },
  ],
  "ok" : 1
} 

Nu hvor du har en generel idé om, hvad du kan opnå med kommandoen usersInfo, er det næste spørgsmål, der kan dukke op, hvilke kommandoer der kan være nyttige til at se på specifikke brugere og flere brugere?

Her er to praktiske eksempler til at illustrere det samme:
Hvis du vil se de specifikke rettigheder og oplysninger for specifikke brugere, men ikke legitimationsoplysningerne, for en bruger “Anthony”, der er defineret i databasen “office”, skal du udføre følgende kommando: “Anthony” er defineret i databasen “office”:

db.runCommand(
  {
    usersInfo:  { user: "Anthony", db: "office" },
    showPrivileges: true
  }
)

Hvis du vil se på en bruger i den aktuelle database, kan du kun nævne brugeren ved navn. Hvis du f.eks. befinder dig i hjemmedatabasen, og der findes en bruger ved navn “Timothy” i hjemmedatabasen, kan du køre følgende kommando:

db.getSiblingDB("home").runCommand(
  {
    usersInfo:  "Timothy",
    showPrivileges: true
  }
)

Derefter kan du bruge et array, hvis du ønsker at se oplysninger om forskellige brugere. Du kan enten medtage de valgfrie felter showCredentials og showPrivileges, eller du kan vælge at udelade dem. Sådan ville kommandoen se ud:

db.runCommand({
usersInfo: [ { user: "Anthony", db: "office" }, { user: "Timothy", db: "home" } ],
  showPrivileges: true
})
revokeRolesFromUser

Du kan bruge kommandoen revokeRolesFromUser til at fjerne en eller flere roller fra en bruger i den database, hvor rollerne findes. Kommandoen revokeRolesFromUser har følgende syntaks:

db.runCommand(
  {
    revokeRolesFromUser: "<user>",
    roles: [
      { role: "<role>", db: "<database>" } | "<role>",
    ],
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

I den ovennævnte syntaks kan du angive både brugerdefinerede og indbyggede roller i feltet roles. I lighed med kommandoen grantRolesToUser kan du angive den rolle, du vil tilbagekalde, i et dokument eller bruge dens navn.

For at kunne udføre kommandoen revokeRolesFromUser med succes skal du have handlingen revokeRole på den angivne database.

Her er et eksempel for at understrege pointen. Enheden productUser00 i produktdatabasen havde følgende roller:

"roles" : [
  {
    "role" : "assetsWriter",
    "db" : "assets"
  },
  {
    "role" : "readWrite",
    "db" : "stock"
  },
  {
    "role" : "read",
    "db" : "products"
  }
]

Følgende revokeRolesFromUser-kommando fjerner to af brugerens roller: “read”-rollen fra products og assetsWriter-rollen fra “assets”-databasen:

use products
db.runCommand( { revokeRolesFromUser: "productUser00",
  roles: [
    { role: "AssetsWriter", db: "assets" },
    "read"
  ],
  writeConcern: { w: "majority" }
} )

Brugeren “productUser00” i databasen “products” har nu kun én rolle tilbage:

"roles" : [
  {
    "role" : "readWrite",
    "db" : "stock"
  }
]

Kommandoer til administration af roller

Roller giver brugere adgang til ressourcer. Flere indbyggede roller kan bruges af administratorer til at styre adgangen til et MongoDB-system. Hvis rollerne ikke dækker de ønskede privilegier, kan du endda gå videre og oprette nye roller i en bestemt database.

dropRole

Med kommandoen dropRole kan du slette en brugerdefineret rolle fra den database, som du kører kommandoen på. Du skal bruge følgende syntaks for at udføre denne kommando:

db.runCommand(
  {
    dropRole: "<role>",
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

For at få den korrekt udført, skal du have handlingen dropRole på den angivne database. Følgende handlinger ville fjerne rollen writeTags fra databasen “products”:

use products
db.runCommand(
  {
    dropRole: "writeTags",
    writeConcern: { w: "majority" }
  }
)
createRole

Du kan bruge kommandoen createRole til at oprette en rolle og angive dens rettigheder. Rollen gælder for den database, som du vælger at køre kommandoen på. Kommandoen createRole ville returnere en fejl i forbindelse med en dobbeltrolle, hvis rollen allerede findes i databasen.

For at udføre denne kommando skal du følge den angivne syntaks:

db.adminCommand(
  {
    createRole: "<new role>",
    privileges: [
      { resource: { <resource> }, actions: [ "<action>", ... ] },
    ],
    roles: [
      { role: "<role>", db: "<database>" } | "<role>",
    ],
    authenticationRestrictions: [
      {
        clientSource: ["<IP>" | "<CIDR range>", ...],
        serverAddress: ["<IP>" | "<CIDR range>", ...]
      },
    ],
    writeConcern: <write concern document>,
    comment: <any> 
  }
)

En rolles privilegier gælder for den database, hvor rollen blev oprettet. Rollen kan arve privilegier fra andre roller i den pågældende database. En rolle, der er oprettet på databasen “admin”, kan f.eks. indeholde privilegier, der gælder for enten en klynge eller alle databaser. Den kan også arve privilegier fra roller, der findes i andre databaser.

Hvis du vil oprette en rolle i en database, skal du have to ting:

  1. grantRole handling på denne database for at nævne privilegier for den nye rolle samt for at nævne roller til at arve fra.
  2. Handlingen createRole på denne databaseresource.

Følgende createRole-kommando opretter en clusterAdmin-rolle i brugerdatabasen:

db.adminCommand({ createRole: "clusterAdmin",
  privileges: [
    { resource: { cluster: true }, actions: [ "addShard" ] },
    { resource: { db: "config", collection: "" }, actions: [ "find", "remove" ] },
    { resource: { db: "users", collection: "usersCollection" }, actions: [ "update", "insert" ] },
    { resource: { db: "", collection: "" }, actions: [ "find" ] }
  ],
  roles: [
    { role: "read", db: "user" }
  ],
  writeConcern: { w: "majority" , wtimeout: 5000 }
})
grantRolesToRole

Med kommandoen grantRolesToRole kan du tildele roller til en brugerdefineret rolle. Kommandoen grantRolesToRole vil påvirke roller i den database, hvor kommandoen udføres.

Denne grantRolesToRole-kommando har følgende syntaks:

db.runCommand(
  {
    grantRolesToRole: "<role>",
    roles: [
     { role: "<role>", db: "<database>" },
    ],
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

Adgangsrettighederne svarer til adgangsrettighederne for kommandoen grantRolesToUser – du skal have en grantRole-handling på en database for at kunne udføre kommandoen korrekt.

I det følgende eksempel kan du bruge kommandoen grantRolesToRole til at opdatere rollen productsReader i databasen “products” til at arve rettighederne for rollen productsWriter:

use products
db.runCommand(
  { 
    grantRolesToRole: "productsReader",
    roles: [
      "productsWriter"
    ],
    writeConcern: { w: "majority" , wtimeout: 5000 }
  }
)
revokePrivilegesFromRole

Du kan bruge revokePrivilegesFromRole til at fjerne de angivne privilegier fra den brugerdefinerede rolle i den database, hvor kommandoen udføres. For korrekt udførelse skal du huske på følgende syntaks:

db.runCommand(
  {
    revokePrivilegesFromRole: "<role>",
    privileges: [
      { resource: { <resource> }, actions: [ "<action>", ... ] },
    ],
    writeConcern: <write concern document>,
    comment: <any> 
  }
)

For at tilbagekalde et privilegium skal mønsteret “resource document” passe til det pågældende privilegiums “resource”-felt. “actions”-feltet kan enten være et nøjagtigt match eller en delmængde.

Tag f.eks. rollen manageRole i produktdatabasen med følgende privilegier, der angiver databasen “managers” som ressource:

{
  "resource" : {
    "db" : "managers",
    "collection" : ""
  },
  "actions" : [
    "insert",
    "remove"
  ]
}

Du kan ikke tilbagekalde handlingerne “insert” eller “remove” fra kun én samling i managers-databasen. Følgende handlinger medfører ingen ændring i rollen:

use managers
db.runCommand(
  {
    revokePrivilegesFromRole: "manageRole",
    privileges: [
      {
        resource : {
          db : "managers",
          collection : "kiosks"
        },
        actions : [
          "insert",
          "remove"
        ]
      }
    ]
  }
)
db.runCommand(
  {
    revokePrivilegesFromRole: "manageRole",
    privileges:
      [
        {
          resource : {
          db : "managers",
          collection : "kiosks"
        },
        actions : [
          "insert"
        ]
      }
    ]
  }
)

For at tilbagekalde “insert”- og/eller “remove”-handlingerne fra rollen manageRole skal du matche ressourcedokumentet nøjagtigt. Følgende operation tilbagekalder f.eks. kun “remove”-handlingen fra det eksisterende privilegium:

use managers
db.runCommand(
  {
    revokePrivilegesFromRole: "manageRole",
    privileges:
      [
        {
          resource : {
            db : "managers",
            collection : ""
        },
        actions : [ "remove" ]
      }
    ]
  }
)

Følgende operation fjerner flere rettigheder fra rollen “executive” i managers-databasen:

use managers
db.runCommand(
  {
    revokePrivilegesFromRole: "executive",
    privileges: [
      {
        resource: { db: "managers", collection: "" },
        actions: [ "insert", "remove", "find" ]
      },
      {
        resource: { db: "managers", collection: "partners" },
        actions: [ "update" ]
      }
    ],
    writeConcern: { w: "majority" }
    }
)
rolesInfo

Kommandoen rolesInfo returnerer oplysninger om privilegier og arv for de angivne roller, herunder både indbyggede og brugerdefinerede roller. Du kan også bruge kommandoen rolesInfo til at hente alle roller, der er omfattet af en database.

Følg denne syntaks for korrekt udførelse:

db.runCommand(
  {
    rolesInfo: { role: <name>, db: <db> },
    showPrivileges: <Boolean>,
    showBuiltinRoles: <Boolean>,
    comment: <any> 
  }
)

Hvis du vil returnere oplysninger om en rolle fra den aktuelle database, kan du angive dens navn som følger:

{ rolesInfo: "<rolename>" }

Hvis du vil returnere oplysninger om en rolle fra en anden database, kan du nævne rollen med et dokument, der nævner rollen og databasen:

{ rolesInfo: { role: "<rolename>", db: "<database>" } }

Følgende kommando returnerer f.eks. oplysninger om rollearv for rollen leder, der er defineret i managers-databasen:

db.runCommand(
   {
      rolesInfo: { role: "executive", db: "managers" }
   }
)

Den næste kommando returnerer oplysninger om rollearv: accountManager på den database, som kommandoen udføres på:

db.runCommand(
   {
      rolesInfo: "accountManager"
   }
)

Den følgende kommando returnerer både rettigheder og rollearv for rollen “executive” som defineret i databasen managers:

db.runCommand(
   {
     rolesInfo: { role: "executive", db: "managers" },
     showPrivileges: true
   }
)

Hvis du vil nævne flere roller, kan du bruge et array. Du kan også nævne hver rolle i arrayet som en streng eller et dokument.

Du bør kun bruge en streng, hvis rollen findes i den database, som kommandoen udføres i:

{
  rolesInfo: [
    "<rolename>",
    { role: "<rolename>", db: "<database>" },
  ]
}

Følgende kommando returnerer f.eks. oplysninger om tre roller på tre forskellige databaser:

db.runCommand(
   {
    rolesInfo: [
      { role: "executive", db: "managers" },
      { role: "accounts", db: "departments" },
      { role: "administrator", db: "products" }
    ]
  }
)

Du kan få vist både rettigheder og rollearv på følgende måde:

db.runCommand(
  {
    rolesInfo: [
      { role: "executive", db: "managers" },
      { role: "accounts", db: "departments" },
      { role: "administrator", db: "products" }
    ],
    showPrivileges: true
  }
)

Indlejring af MongoDB-dokumenter for bedre ydeevne

Dokumentdatabaser som MongoDB giver dig mulighed for at definere dit skema i overensstemmelse med dine behov. For at skabe optimale skemaer i MongoDB kan du indlejre dokumenterne. Så i stedet for at matche din applikation til en datamodel kan du opbygge en datamodel, der passer til dit brugsscenarie.

Med indlejrede dokumenter kan du gemme relaterede data, som du får adgang til sammen. Når du designer skemaer til MongoDB, anbefales det, at du som standard indlejrer dokumenter. Brug kun database-side eller program-side joins og referencer, når det er værd at bruge dem.

Sørg for, at arbejdsbyrden kan hente et dokument så ofte som nødvendigt. Samtidig skal dokumentet også have alle de data, det har brug for. Dette er afgørende for din applikations ekstraordinære ydeevne.

Nedenfor finder du et par forskellige mønstre til at indlejre dokumenter:

Mønster til indlejrede dokumenter

Du kan bruge dette til at indlejre selv komplicerede understrukturer i de dokumenter, som de bruges sammen med. Ved at indlejre sammenhængende data i et enkelt dokument kan du mindske antallet af læseoperationer, der er nødvendige for at hente data. Generelt bør du strukturere dit skema således, at dit program modtager alle de nødvendige oplysninger i en enkelt læseoperation. Derfor er den regel, du skal huske på her, at det, der bruges sammen, skal gemmes sammen.

Mønsteret med indlejret delmængde

Det indlejrede undergruppemønster er et hybridtilfælde. Du ville bruge det til en separat samling af en lang liste af relaterede elementer, hvor du kan holde nogle af disse elementer ved hånden til visning.

Her er et eksempel, der indeholder en liste over filmanmeldinger:

> db.movie.findOne()
{   
  _id: 321475,   
  title: "The Dark Knight"
}  
> db.review.find({movie_id: 321475})
{   
  _id: 264579,   
  movie_id: 321475,   
  stars: 4   
  text: "Amazing"   
}
{   
  _id: 375684,   
  movie_id: 321475,   
  stars:5,   
  text: "Mindblowing"
}

Forestil dig tusind lignende anmeldelser, men du har kun tænkt dig at vise de to seneste anmeldelser, når du viser en film. I dette scenario giver det mening at gemme denne delmængde som en liste i filmdokumentet:

> db.movie.findOne({_id: 321475})   
{   
  _id: 321475,   
  title: "The Dark Knight",   
  recent_reviews: [   
    {_id: 264579, stars: 4, text: "Amazing"},   
    {_id: 375684, stars: 5, text: "Mindblowing"}   
  ]   
}</code

Hvis du rutinemæssigt har adgang til en delmængde af relaterede elementer, skal du sørge for at indlejre den.

Uafhængig adgang

Du ønsker måske at gemme underdokumenter i deres samling for at adskille dem fra deres overordnede samling.

Tag f.eks. en virksomheds produktlinje. Hvis virksomheden sælger et lille sæt produkter, vil du måske gemme dem i virksomhedsdokumentet. Men hvis du vil genbruge dem på tværs af virksomheder eller få direkte adgang til dem via deres lagerholdingsenhed (SKU), skal du også gemme dem i deres samling.

Hvis du manipulerer eller får adgang til en enhed uafhængigt, skal du lave en samling for at gemme den separat for at sikre bedste praksis.

Ubundne lister

Lagring af korte lister med relaterede oplysninger i deres dokument har en ulempe. Hvis din liste fortsætter med at vokse ukontrolleret, bør du ikke lægge den i et enkelt dokument. Det skyldes, at du ikke ville kunne understøtte den i særlig lang tid.

Der er to grunde til dette. For det første har MongoDB en grænse for størrelsen af et enkelt dokument. For det andet, hvis du tilgår dokumentet med for mange frekvenser, vil du se negative resultater af ukontrolleret hukommelsesforbrug.

For at sige det enkelt, hvis en liste begynder at vokse ubegrænset, skal du lave en samling for at gemme den separat.

Udvidet referencemønster

Det udvidede referencemønster er ligesom undergruppemønsteret. Det optimerer også oplysninger, som du regelmæssigt får adgang til at gemme på dokumentet.

Her udnyttes det i stedet for en liste, når et dokument henviser til et andet dokument, der er til stede i samme samling. Samtidig lagrer det også nogle felter fra det andet dokument for at have adgang til dem hurtigt.

For eksempel:

> db.movie.findOne({_id: 245434})
{   
  _id: 245434,   
  title: "Mission Impossible 4 - Ghost Protocol",   
  studio_id: 924935,   
  studio_name: "Paramount Pictures"   
}

Som du kan se, er “the studio_id” gemt, så du kan finde flere oplysninger om det studie, der har lavet filmen. Men studiets navn er også kopieret til dette dokument for at gøre det mere enkelt.

Hvis du vil indlejre oplysninger fra ændrede dokumenter regelmæssigt, skal du huske at opdatere de dokumenter, hvor du har kopieret oplysningerne, når de ændres. Med andre ord, hvis du rutinemæssigt har adgang til nogle felter fra et dokument, der er refereret til, skal du indlejre dem.

Sådan overvåger du MongoDB

Du kan bruge overvågningsværktøjer som Kinsta APM til at debugge lange API-opkald, langsomme databaseforespørgsler, lange eksterne URL-forespørgsler, for blot at nævne nogle få. Du kan endda udnytte kommandoer til at forbedre databasens ydeevne. Du kan også bruge dem til at inspicere sundheden af dine databaseinstanser.

Hvorfor skal du overvåge MongoDB-databaser?

Et vigtigt aspekt af planlægning af databaseadministration er overvågning af din klynges ydeevne og sundhed. MongoDB Atlas håndterer størstedelen af administrationsarbejdet gennem sine fejltolerance/skaleringsevner.

På trods af det skal brugerne vide, hvordan de skal spore klynger. De skal også vide, hvordan de skalerer eller justerer alt det, de har brug for, før de rammer en krise.

Ved at overvåge MongoDB-databaser kan du:

  • Overvåg udnyttelsen af ressourcerne.
  • Forstå den aktuelle kapacitet i din database.
  • Reager og registrer problemer i realtid for at forbedre din applikations stak.
  • Observere tilstedeværelsen af præstationsproblemer og unormal adfærd.
  • Afstemme med dine krav til styring/databeskyttelse og serviceniveauaftaler (SLA).

Vigtige målepunkter til overvågning

Når du overvåger MongoDB, er der fire vigtige aspekter, du skal huske på:

MongoDB Hardware Metrics

Her er de primære metrikker til overvågning af hardware:

Normaliseret proces-CPU

Det er defineret som den procentdel af den tid, som CPU’en bruger på applikationssoftware, der vedligeholder MongoDB-processen.

Du kan skalere dette til et interval på 0-100% ved at dividere det med antallet af CPU-kerner. Den omfatter CPU, der udnyttes af moduler som f.eks. kerne og bruger.

En høj kerne-CPU kan vise, at CPU’en er opbrugt via operativsystemets operationer. Men brugeren i forbindelse med MongoDB-operationer kan være den grundlæggende årsag til CPU-udmattelse.

Normaliseret system-CPU

Det er den procentdel af tiden, som CPU’en har brugt på systemopkald til at betjene denne MongoDB-proces. Du kan skalere den til et interval på 0-100% ved at dividere den med antallet af CPU-kerner. Den dækker også den CPU, der bruges af moduler som iowait, user, kernel, steal osv.

Bruger-CPU eller høj kerne kan vise CPU-udmattelse gennem MongoDB-operationer (software). Høj iowait kan være forbundet med udtømning af lagerplads, der forårsager CPU-udtømning.

Disk IOPS

Disk IOPS er det gennemsnitlige forbrug af IO-operationer pr. sekund på MongoDB’s diskpartition.

Disk Latency

Dette er diskpartitionens læse- og skrivetid på disken i millisekunder i MongoDB. Høje værdier (>500 ms) viser, at lagringslaget kan påvirke MongoDB’s ydeevne.

Systemhukommelse

Brug systemhukommelsen til at beskrive den fysiske hukommelsesbytes, der bruges, i forhold til den tilgængelige frie plads.

Den tilgængelige metrik giver en tilnærmelsesvis angivelse af antallet af bytes af tilgængelig systemhukommelse. Du kan bruge dette til at udføre nye programmer uden swapping.

Fri diskplads

Dette er defineret som den samlede mængde bytes af ledig diskplads på MongoDB’s diskpartition. MongoDB Atlas giver mulighed for automatisk skalering baseret på denne metrik.

Swap-forbrug

Du kan udnytte en graf for swap-brug til at beskrive, hvor meget hukommelse der er placeret på swap-enheden. En høj brug af metrikken i denne graf viser, at swap-memory bliver udnyttet. Dette viser, at hukommelsen er underforsynet til den aktuelle arbejdsbyrde.

MongoDB Cluster’s forbindelses- og driftsmålinger

Her er de vigtigste metrikker for Operation og Connection Metrics:

Operation Execution Times

Den gennemsnitlige operationstid (skrive- og læseoperationer), der udføres i den valgte prøveperiode.

Opcounters

Det er den gennemsnitlige hastighed af udførte operationer pr. sekund i den valgte prøveperiode. Grafen/metrikken Opcounters viser fordelingen af operationer på operationstyper og hastighed for instansen.

Connections

Denne måleenhed henviser til antallet af åbne forbindelser til instansen. Høje spidser eller tal kan pege på en suboptimal forbindelsesstrategi enten fra den server, der ikke reagerer, eller fra klientsiden.

Targeting queries and query performers

Dette er den gennemsnitlige hastighed pr. sekund i den valgte prøveperiode af scannede dokumenter. For forespørgselsudførere er dette under evaluering af forespørgselsplaner og forespørgsler. For forespørgselsmålsætning viser forholdet mellem antallet af scannede dokumenter og antallet af returnerede dokumenter.

Et højt talforhold peger på suboptimale operationer. Disse operationer scanner en masse dokumenter for at returnere en mindre del.

Scan and order

Den beskriver den gennemsnitlige hastighed pr. sekund i den valgte prøveperiode for forespørgsler. Den returnerer sorterede resultater, som ikke kan udføre sorteringsoperationen ved hjælp af et indeks.

Queues

Køer kan beskrive antallet af operationer, der venter på en lås, enten skrive- eller læseoperationer. Høje køer kan være et tegn på, at skemaet ikke er designet optimalt. Det kan også være tegn på modstridende skriveveje, der skaber stor konkurrence om databasens ressourcer.

MongoDB Replication Metrics

Her er de primære metrikker til replikeringsovervågning:

Replication Oplog Window

Denne metrik viser det omtrentlige antal timer, der er tilgængelige i den primære replikationsoplog. Hvis en sekundær replikator halter mere end dette beløb, kan den ikke følge med og har brug for en fuld resynkronisering.

Replication delay

Replikationsforsinkelse er defineret som det omtrentlige antal sekunder, som en sekundær knude er bagud i forhold til den primære knude i skriveoperationer. Et stort replikation delay tyder på, at en sekundær knude har problemer med at replikere. Det kan påvirke din operations latenstid i betragtning af forbindelsernes læse-/skriveinteresse.

Replication room

Denne måleenhed henviser til forskellen mellem den primære replikerings oplogvindue og den sekundære replikeringsforsinkelse. Hvis denne værdi går til nul, kan det medføre, at en sekundær replikation går i RECOVERING-tilstand.

Opcounters – repl

Opcounters – repl er defineret som den gennemsnitlige hastighed af replikationsoperationer, der udføres pr. sekund i den valgte prøveperiode. Med opcounters – graph/metric kan du se på operationshastigheden og fordelingen af operationstyperne for den angivne instans.

Oplog GB/time

Dette er defineret som den gennemsnitlige hastighed af gigabyte oplog, som den primære genererer pr. time. Store uventede mængder af oplog kan tyde på en meget utilstrækkelig skrivearbejdsbyrde eller et problem med skemadesignet.

Værktøjer til overvågning af MongoDB’s ydeevne

MongoDB har indbyggede brugergrænsefladeværktøjer i Cloud Manager, Atlas og Ops Manager til overvågning af ydeevne. Det giver også nogle uafhængige kommandoer og værktøjer til at se på mere råbaserede data. Vi vil tale om nogle værktøjer, som du kan køre fra en host, der har adgang og passende roller til at kontrollere dit miljø:

mongotop

Du kan udnytte denne kommando til at spore den tid, som en MongoDB-instans bruger på at skrive og læse data pr. samling. Brug følgende syntaks:

mongotop <options> <connection-string> <polling-interval in seconds>

rs.status()

Denne kommando returnerer replikasætstatus. Den udføres fra synspunktet for det medlem, hvor metoden udføres.

mongostat

Du kan bruge kommandoen mongostat til at få et hurtigt overblik over status for din MongoDB-serverinstans. For at opnå et optimalt output kan du bruge den til at overvåge en enkelt instans for en bestemt begivenhed, da den giver et realtidsbillede.

Udnyt denne kommando til at overvåge grundlæggende serverstatistik såsom låsekøer, operationsfordeling, MongoDB-hukommelsesstatistik og forbindelser/netværk:

mongostat <options> <connection-string> <polling interval in seconds>

dbStats

Denne kommando returnerer lagerstatistikker for en bestemt database, f.eks. antallet af indekser og deres størrelse, samlede indsamlingsdata i forhold til lagerstørrelse og indsamlingsrelaterede statistikker (antal samlinger og dokumenter).

db.serverStatus()

Du kan udnytte kommandoen db.serverStatus() til at få et overblik over databasens tilstand. Den giver dig et dokument, der repræsenterer den aktuelle instans metriske tællere. Udfør denne kommando med jævne mellemrum for at samle statistikker om instansen.

collStats

Kommandoen collStats indsamler statistikker svarende til dem, der tilbydes af dbStats på samlingsniveau. Dens output består af en optælling af objekter i samlingen, mængden af diskplads, som samlingen bruger, samlingens størrelse og oplysninger om dens indekser for en given samling.

Du kan bruge alle disse kommandoer til at tilbyde rapportering og overvågning af databaseserveren i realtid, så du kan overvåge databasens ydeevne og fejl og hjælpe med at træffe informerede beslutninger om at forfine en database.

Sådan Slettes en MongoDB Database

For at slette en database, du har oprettet i MongoDB, skal du oprette forbindelse til den via et keyword’s use.

Lad os sige, at du har oprettet en database ved navn “Engineers”. For at oprette forbindelse til databasen skal du bruge følgende kommando:

use Engineers

Derefter skriver du db.dropDatabase() for at fjerne denne database. Efter udførelsen er dette det resultat, du kan forvente:

{ "dropped"  :  "Engineers", "ok" : 1 }

Du kan køre kommandoen showdbs for at kontrollere, om databasen stadig eksisterer.

Opsummering

Hvis du vil presse hver eneste dråbe værdi ud af MongoDB, skal du have en stærk forståelse af de grundlæggende principper. Derfor er det centralt at kende MongoDB-databaser som din egen håndryg. Dette kræver, at du først gør dig bekendt med metoderne til at oprette en database.

I denne artikel kaster vi lys over de forskellige metoder, du kan bruge til at oprette en database i MongoDB, efterfulgt af en detaljeret beskrivelse af nogle smarte MongoDB-kommandoer, så du kan holde styr på dine databaser. Endelig afrundede vi diskussionen ved at diskutere, hvordan du kan udnytte indlejrede dokumenter og værktøjer til overvågning af ydeevne i MongoDB for at sikre, at din arbejdsgang fungerer optimalt effektivt.

Hvad er din holdning til disse MongoDB-kommandoer? Gik vi glip af et aspekt eller en metode, som du gerne ville have set her? Lad os vide det i kommentarerne!

Salman Ravoof

Salman Ravoof is a self-taught web developer, writer, creator, and a huge admirer of Free and Open Source Software (FOSS). Besides tech, he's excited by science, philosophy, photography, arts, cats, and food. Learn more about him on his website, and connect with Salman on Twitter.