Baserat på dina krav på din programvara så kan du prioritera flexibilitet, skalbarhet, prestanda eller snabbhet. Av den anledningen så blir utvecklare och företag ofta förvirrade när de ska välja en databas för sina behov. Om du behöver en databas som ger hög flexibilitet och skalbarhet samt dataaggregering för kundanalys så kan MongoDB vara rätt för dig!

I den här artikeln så diskuterar vi MongoDB-databasens struktur och hur du skapar, övervakar och hanterar din databas! Låt oss komma igång.

Hur är en MongoDB-databas uppbyggd?

MongoDB är en schemalös NoSQL-databas. Detta innebär att du inte anger en struktur för tabellerna/databaserna som du gör för SQL-databaser.

Visste du att NoSQL-databaser faktiskt är snabbare än relationsdatabaser? Detta beror på egenskaper som indexering, sharding och aggregeringspipelines. MongoDB är känd för sitt snabba utförande av frågor. Det är därför som den föredras av företag som Google, Toyota och Forbes.

Nedan ska vi utforska några viktiga egenskaper hos MongoDB.

Dokument

MongoDB har en dokumentdatamodell som lagrar data som JSON-dokument. Dokumenten mappas naturligt till objekten i applikationskoden, vilket gör det enklare för utvecklare att använda dem.

I en tabell i en relationsdatabas så måste du lägga till en kolumn för att lägga till ett nytt fält. Så är inte fallet med fält i ett JSON-dokument. Fält i ett JSON-dokument kan skilja sig från dokument till dokument, så de kommer inte att läggas till i varje post i databasen.

Dokument kan lagra strukturer som matriser som kan vara inbäddade för att uttrycka hierarkiska relationer. MongoDB konverterar dessutom dokument till en binär JSON-typ (BSON). Detta säkerställer en snabbare åtkomst och ökat stöd för olika datatyper som sträng, heltal, boolska tal och mycket mer!

Replikuppsättningar

När du skapar en ny databas i MongoDB så skapar systemet automatiskt minst två ytterligare kopior av dina data. Dessa kopior kallas ”replikor” och de replikerar kontinuerligt data mellan dem, vilket säkerställer en förbättrad tillgänglighet för dina data. De erbjuder även skydd mot driftstopp vid systemfel eller planerat underhåll.

Samlingar

En samling är en grupp dokument som är kopplade till en databas. De liknar tabeller i relationsdatabaser.

Samlingar är dock mycket mer flexibla. För det första så är de inte beroende av ett schema. För det andra så behöver dokumenten inte vara av samma datatyp!

Om du vill visa en lista över de samlingar som hör till en databas så använder du kommandot listCollections.

Aggregeringspipelines

Du kan använda det här ramverket för att fånga in flera operatörer och uttryck. Det är flexibelt eftersom det gör det möjligt att bearbeta, omvandla och analysera data av vilken struktur som helst.

Tack vare detta så tillåter MongoDB snabba dataflöden och funktioner över 150 operatörer och uttryck. Den har även flera steg, som unionssteget, som flexibelt sätter ihop resultat från flera samlingar.

Index

Du kan indexera alla fält i ett MongoDB-dokument för att öka effektiviteten och förbättra sökhastigheten. Indexering sparar tid genom att indexet skannas för att begränsa de dokument som inspekteras. Visst är detta mycket bättre än att läsa varje dokument i samlingen?

Du kan använda olika indexeringsstrategier, inklusive sammansatta index på flera fält. Säg exempelvis att du har flera dokument som innehåller den anställdes för- och efternamn i separata fält. Om du vill att för- och efternamn ska returneras så kan du skapa ett index som både innehåller ”Efternamn” och ”Förnamn”. Detta är mycket bättre än att ha ett index för ”efternamn” och ett annat för ”förnamn”.

Du kan använda verktyg som Performance Advisor för att ytterligare förstå vilka frågor som kan dra nytta av index.

Delning av

Sharding distribuerar en enda datamängd över flera databaser. Datamängden kan sedan lagras på flera maskiner för att öka den totala lagringskapaciteten i ett system. Detta beror på att större datamängder delas upp i mindre delar och lagras i olika datanoder.

MongoDB delar upp data på samlingsnivå och distribuerar dokumenten i en samling över alla delar i ett kluster. Detta säkerställer skalbarhet genom att arkitekturen kan hantera de största applikationerna.

Så här skapar du en MongoDB-databas

Du måste först installera rätt MongoDB-paket som är lämpligt för ditt operativsystem. Gå till sidan ”Ladda ner MongoDB Community Server”. Bland de tillgängliga alternativen så väljer du den senaste ”versionen”, ”paketformatet” som zip-fil och ”plattformen” som ditt operativsystem och klickar på ”Ladda ner” enligt bilden nedan:

Den här bilden visar de tillgängliga alternativen- Version, Plattform och Paket när du laddar ner MongoDB Community Server.
Hämtningsprocessen för MongoDB Community Server. (Bildkälla: MongoDB Community Server)

Processen är ganska okomplicerad, så du kommer att ha MongoDB installerat i ditt system på nolltid!

När du har gjort installationen så öppnar du din kommandotolk och skriver in mongod -version för att verifiera den. Om du inte får följande utdata utan istället ser en rad fel så kan du behöva installera om den:

Detta är ett kodavsnitt för att kontrollera MongoDB-versionen efter installationen.
Verifierar MongoDB-versionen. (Bildkälla: configserverfirewall)

Använda MongoDB Shell

Innan vi börjar så ska du se till att:

  • Din klient har Transport Layer Security och finns på din IP-lista.
  • Du har ett användarkonto och lösenord på det önskade MongoDB-klustret.
  • Du har installerat MongoDB på din enhet.

Steg 1: Åtkomst till MongoDB Shell

Starta MongoDB-servern genom att följa instruktionerna för varje operativsystem. För Windows, skriv följande kommando. För andra operativsystem, se MongoDB-dokumentationen.

net start MongoDB

Detta bör ge följande resultat:

Kör MongoDB-server (Bildkälla: c-sharpcorner)
Kör MongoDB-server (Bildkälla: c-sharpcorner)

Det föregående kommandot initialiserade MongoDB-servern. För att köra det så måste vi skriva in mongo i kommandotolken.

Kör MongoDB-skal. (Bildkälla: bmc)
Kör MongoDB-skal. (Bildkälla: bmc)

Här i MongoDB Shell så kan vi utföra kommandon för att skapa databaser, infoga data, redigera data, utfärda administrativa kommandon och radera data.

Steg 2: Skapa din databas

Till skillnad från vanliga relationsdatabaser har MongoDB inget kommando för att skapa databas. Det finns istället ett nyckelord som heter use som växlar till en angiven databas. Om databasen inte finns så kommer det att skapas en ny databas, annars kommer det att länkas till den befintliga databasen.

För att starta en databas som heter ”company” skriver du exempelvis:

use Company
Skapa en databas i MongoDB.
Skapa en databas i MongoDB.

Du kan skriva in db för att bekräfta den databas som du just skapat i ditt system. Om den nya databasen som du skapade dyker upp så har du lyckats ansluta till den.

Om du vill kontrollera de befintliga databaserna så skriver du show dbs och får fram alla databaser i ditt system:

Visar databaser i MongoDB.
Visar databaser i MongoDB.

Som standard så skapar installationen av MongoDB databaserna admin, config och local.

Märkte du att databasen som vi skapade inte visas? Detta beror på att vi ännu inte har sparat värden i databasen! Vi kommer att diskutera insättning under avsnittet om databashantering.

Användning av Atlas UI

Du kan även komma igång med MongoDB: s databastjänst Atlas. Även om du kan behöva betala för att få tillgång till vissa funktioner i Atlas, så är de flesta databasfunktionerna tillgängliga i den kostnadsfria varianten. Funktionerna i den kostnadsfria varianten är mer än tillräckliga för att skapa en MongoDB-databas.

Innan vi börjar så ska du se till att:

  1. Din IP finns med på listan över tillåtna enheter.
  2. Du har ett användarkonto och lösenord på det MongoDB-kluster som du vill använda.

För att skapa en MongoDB-databas med AtlasUI så öppnar du ett webbläsarfönster och loggar in på https://cloud.mongodb.com. På din klustersida så klickar du på Bläddra bland samlingar. Om det inte finns några databaser i klustret så kan du skapa din databas genom att klicka på knappen Lägg till min egen data.

Du kommer att uppmanas att ange ett databas- och samlingsnamn. När du har namngett dem så klickar du på Skapa och sen är du klar! Du kan nu ange nya dokument eller ansluta till databasen med hjälp av drivrutiner.

Hantering av din MongoDB-databas

I det här avsnittet så går vi igenom några smarta sätt att hantera din MongoDB-databas på ett effektivt sätt. Du kan göra detta antingen genom att använda MongoDB-kompassen eller genom samlingar.

Användning av samlingar

Medan relationsdatabaser har väldefinierade tabeller med specificerade datatyper och kolumner så har NoSQL samlingar istället för tabeller. Dessa samlingar har ingen struktur och dokumenten kan variera – du kan ha olika datatyper och fält utan att behöva matcha ett annat dokuments format i samma samling.

För att demonstrera detta så skapar vi en samling som heter ”Employee” och lägger till ett dokument i den:

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

Om insättningen är framgångsrik så kommer WriteResult({ "nInserted" : 1 }) att returneras:

Framgångsrik insättning i MongoDB.
Framgångsrik insättning i MongoDB.

Här hänvisar ”db” till den för närvarande anslutna databasen. ”Employee” är den nyligen skapade samlingen i företagsdatabasen.

Vi har inte ställt in någon primärnyckel här eftersom MongoDB automatiskt skapar ett primärnyckelfält som heter ”_id” och ställer in ett standardvärde för detta.

Kör nedanstående kommando för att kolla upp samlingen i JSON-format:

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

Utmatning:

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

Du kan ändra värdet på standardprimärnyckeln, även om värdet ”_id” tilldelas automatiskt. Den här gången så infogar vi ett annat dokument i databasen ”Employee” med värdet ”_id” som ”1”:

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

När vi kör kommandot db.Employee.find().forEach(printjson) så får vi följande resultat:

Dokument i samlingen med deras primära nyckel.
Dokument i samlingen med deras primära nyckel.

I ovanstående utdata så sätts värdet ”_id” för ”Ava” till ”1” i stället för att det tilldelas ett värde automatiskt.

Nu när vi har lyckats lägga till värden i databasen så kan vi kontrollera om den dyker upp under de befintliga databaserna i vårt system med hjälp av följande kommando:

show dbs
Visar listan över databaser.
Visar listan över databaser.

Och voila! Du har framgångsrikt skapat en databas i ditt system!

Användning av MongoDB-kompassen

Även om vi kan arbeta med MongoDB-servrar från Mongo Shell så kan det ibland vara tråkigt. Du kan uppleva detta i en produktionsmiljö.

Det finns dock ett kompassverktyg (med det passande namnet Compass) som har skapats av MongoDB och som kan göra det enklare. Det har ett bättre GUI och har lagt till funktioner som datavisualisering, prestandaprofilering och CRUD-åtkomst (skapa, läsa, uppdatera, ta bort) till data, databaser och samlingar.

Du kan ladda ner Compass IDE för ditt operativsystem och installera det med dess enkla process.

Öppna sedan programmet och skapa en anslutning till servern genom att klistra in anslutningssträngen. Om du inte kan hitta den så kan du klicka på Fyll i anslutningsfält individuellt. Om du inte ändrade portnumret när du installerade MongoDB så är det bara att klicka på anslutningsknappen, så är du inne! I annat fall så anger du bara de värden som du ställde in och klickar på Anslut.

Fönstret Ny anslutning i MongoDB.. (Bildkälla: mongodb)
Fönstret Ny anslutning i MongoDB. (Bildkälla: mongodb)

Ange sedan hostnamn, port och autentisering i fönstret Ny anslutning.

I MongoDB Compass så kan du skapa en databas och lägga till dess första samling på samma gång. Så här gör du:

  1. Klicka på Skapa databas för att öppna prompten.
  2. Ange namnet på databasen och dess första samling.
  3. Klicka på Skapa en databas.

Du kan lägga in fler dokument i din databas genom att klicka på databasens namn och sedan klicka på samlingens namn för att se fliken Dokument. Du kan sedan klicka på knappen Lägg till data för att lägga in ett eller flera dokument i samlingen.

När du lägger till dina dokument så kan du ange dem ett i taget eller som flera dokument i en matris. Om du lägger till flera dokument så ska du se till att dessa kommaseparerade dokument omsluts av hakparenteser. exempelvis:

{ _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" ] }

Klicka slutligen på Infoga för att lägga till dokumenten i samlingen. Så här kan ett dokument se ut:

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

Här är fältnamnen ”StudentID” och ”StudentName”. Fältvärdena är ”1” respektive ”JohnDoe”.

Användbara kommandon

Du kan hantera dessa samlingar med hjälp av kommandon för rollhantering och användarhantering.

Kommandon för användarhantering

MongoDB:s användarhanteringskommandon inkluderar kommandon som gäller användaren. Vi kan skapa, uppdatera och ta bort användarna med hjälp av dessa kommandon.

dropUser

Det här kommandot tar bort en enskild användare från den angivna databasen. Nedan följer syntaxen:

db.dropUser(username, writeConcern)

Här är username ett obligatoriskt fält som anger namnet på användaren som ska tas bort från databasen. Det valfria fältet writeConcern innehåller nivån av skrivproblem för borttagningsoperationen. Nivån på skrivproblem kan bestämmas av det valfria fältet writeConcern.

Innan du tar bort en användare som har rollen userAdminAnyDatabase så ska du se till att det finns minst en annan användare som har användaradministrationsrättigheter.

I det här exemplet så tar vi bort användaren ”user26” i testdatabasen:

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

Utmatning:

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

Detta kommando skapar en ny användare för den angivna databasen enligt följande:

db.createUser(user, writeConcern)

Här är user ett obligatoriskt fält som innefattar dokumentet med autentiserings- och åtkomstinformation om den användare som ska skapas. Det valfria fältet writeConcern innefattar nivån för skrivskydd för skapandet. Nivån på skrivbehörigheten kan bestämmas av det valfria fältet writeConcern.

createUser ger ett felmeddelande om dubbla användare om användaren redan finns i databasen.

Du kan skapa en ny användare i testdatabasen på följande sätt:

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

Utmatningen ser ut på följande sätt:

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

Du kan använda det här kommandot för att bevilja ytterligare roller till en användare. Om du vill använda det så måste du tänka på följande syntax:

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

Du kan både ange användardefinierade och inbyggda roller i de roller som nämns ovan. Om du vill ange en roll som finns i samma databas som grantRolesToUser så kan du antingen ange rollen med ett dokument, enligt nedan:

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

Eller så kan du ange rollen med rollens namn. exempelvis:

"readWrite"

Om du vill ange en roll som finns i en annan databas så måste du ange rollen med ett annat dokument.

Om du vill bevilja en roll i en databas så behöver du åtgärden grantRole i den angivna databasen.

Här är ett exempel för att ge dig en tydlig bild. Ta exempelvis användaren productUser00 i produktdatabasen med följande roller:

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

Operationen grantRolesToUser ger ”productUser00” rollen readWrite i lagerdatabasen och läsrollen i produktdatabasen:

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

Användaren productUser00 i produktdatabasen har nu följande roller:

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

Du kan använda kommandot usersInfo för att få tillbaka information om en eller flera användare. Här är syntaxen:

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

När det gäller åtkomst så kan användarna alltid titta på sin egen information. För att titta på en annan användares information så måste användaren som kör kommandot ha privilegier som inkluderar åtgärden viewUser i den andra användarens databas.

När du kör kommandot userInfo så kan du få följande information beroende på de angivna alternativen:

{
  "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 när du har en allmän uppfattning om vad du kan åstadkomma med kommandot usersInfo så är nästa fråga rätt så uppenbar: Vilka kommandon kan vara praktiska för att titta på specifika användare och flera användare?

Här är två praktiska exempel för att illustrera detta:
Du kanske vill titta på specifika privilegier och information för specifika användare, men inte på autentiseringsuppgifter. för användaren ”Anthony” som definieras i databasen ”office”, så utför du följande kommando: ”Anthony” är en användare som är definierad i databasen ”office”:

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

Om du vill titta på en användare i den aktuella databasen så kan du bara nämna användaren vid namn. Om du exempelvis befinner dig i hemdatabasen och en användare som heter ”Timothy” finns i hemdatabasen så kan du köra följande kommando:

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

Därefter så kan du använda en array om du vill titta på information om olika användare. Du kan antingen inkludera de valfria fälten showCredentials och showPrivileges, eller så kan du välja att utelämna dem. Så här skulle kommandot se ut:

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

Du kan använda kommandot revokeRolesFromUser för att ta bort en eller flera roller från en användare i den databas där rollerna finns. Kommandot revokeRolesFromUser har följande syntax:

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

I syntaxen ovan så kan du ange både användardefinierade och inbyggda roller i fältet roles. I likhet med kommandot grantRolesToUser så kan du ange den roll som du vill återkalla i ett dokument eller använda dess namn.

För att kunna utföra kommandot revokeRolesFromUser så måste du ha åtgärden revokeRole i den angivna databasen.

Här är ett exempel för att förklara vad som gäller. Enheten productUser00 i produktdatabasen hade följande roller:

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

Följande kommando revokeRolesFromUser tar bort två av användarens roller: rollen ”read” från products och rollen assetsWriter från databasen ”assets”:

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

Användaren ”productUser00” i produktdatabasen har nu endast en roll kvar:

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

Kommandon för rollhantering

Roller ger användare tillgång till resurser. Flera inbyggda roller kan användas av administratörer för att kontrollera åtkomsten till ett MongoDB-system. Om rollerna inte täcker de önskade privilegierna så kan du till och med gå längre och skapa nya roller i en viss databas.

dropRole

Med kommandot dropRole så kan du ta bort en användardefinierad roll från den databas som du kör kommandot på. För att utföra det här kommandot så använder du följande syntax:

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

För att du ska kunna utföra åtgärden så måste du ha åtgärden dropRole på den angivna databasen. Följande åtgärder skulle ta bort rollen writeTags från databasen ”products”:

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

Du kan använda kommandot createRole för att skapa en roll och ange dess privilegier. Rollen gäller för den databas som du väljer att köra kommandot på. Kommandot createRole skulle ge ett felmeddelande om dubbla roller om rollen redan finns i databasen.

Följ syntaxen för att utföra kommandot:

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 rolls privilegier gäller för den databas där rollen skapades. Rollen kan ärva privilegier från andra roller i sin databas. En roll som har skapats i databasen ”admin” kan exempelvis innehålla privilegier som antingen gäller ett kluster eller alla databaser. Den kan även ärva privilegier från roller som finns i andra databaser.

För att skapa en roll i en databas så måste du ha två saker:

  1. Åtgärden grantRole på den databasen för att nämna privilegier för den nya rollen samt för att nämna roller att ärva ifrån.
  2. Åtgärden createRole på den databasresursen.

Följande kommando createRole skapar en roll clusterAdmin i användardatabasen:

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 kommandot grantRolesToRole så kan du tilldela roller till en användardefinierad roll. Kommandot grantRolesToRole påverkar rollerna i den databas där kommandot utförs.

Kommandot grantRolesToRole har följande syntax:

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

grantRolesToUser Du behöver en grantRole -åtgärd i en databas för att kommandot ska kunna utföras korrekt.

I följande exempel så kan du använda kommandot grantRolesToRole för att uppdatera rollen productsReader i databasen ”products” så att den ärver rättigheterna för rollen productsWriter:

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

Du kan använda revokePrivilegesFromRole för att ta bort de angivna privilegierna från den användardefinierade rollen i den databas där kommandot utförs. För att kommandot ska kunna utföras korrekt så måste du tänka på följande syntax:

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

För att återkalla en rättighet så måste mönstret ”resursdokument” matcha rättighetens fält ”resource”. Fältet ”actions” kan antingen vara en exakt matchning eller en delmängd.

Tänk exempelvis på rollen manageRole i produktdatabasen med följande privilegier som anger databasen ”managers” som resurs:

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

Du kan inte återkalla åtgärderna ”infoga” eller ”ta bort” från endast en samling i managers-databasen. Följande åtgärder orsakar 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"
        ]
      }
    ]
  }
)

För att återkalla åtgärderna ”infoga” och/eller ”ta bort” från rollen manageRole så måste du matcha resursdokumentet exakt. Följande åtgärd återkallar exempelvis endast åtgärden ”ta bort” från den befintliga rättigheten:

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

Följande åtgärd tar bort flera privilegier från rollen ”executive” i managerdatabasen:

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

Kommandot rolesInfo returnerar information om privilegier och arv för angivna roller, inklusive både inbyggda och användardefinierade roller. Du kan även använda kommandot rolesInfo för att hämta alla roller som är kopplade till en databas.

För korrekt utförande, följ den här syntaxen:

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

Om du vill hämta information om en roll från den aktuella databasen så kan du ange dess namn på följande sätt:

{ rolesInfo: "<rolename>" }

Om du vill få tillbaka information om en roll från en annan databas så kan du nämna rollen i ett dokument som nämner rollen och databasen:

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

Följande kommando returnerar exempelvis information om roll-arv för rollen manager som har definierats i databasen managers:

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

Nästa kommando returnerar information om arv av roller: accountManager i den databas där kommandot utförs:

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

Följande kommando returnerar både privilegier och roll-arv för rollen ”executive” som har definierats i databasen managers:

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

Om du vill nämna flera roller så kan du använda en array. Du kan även nämna varje roll i matrisen som en sträng eller ett dokument.

Du bör endast använda en sträng om rollen finns i den databas där kommandot utförs:

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

Följande kommando ger exempelvis information om tre roller i tre olika databaser:

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

Du kan få fram både privilegier och roll-arv på följande sätt:

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

Inbäddning av MongoDB-dokument för bättre prestanda

Dokumentdatabaser som MongoDB låter dig definiera ditt schema enligt dina behov. För att skapa optimala scheman i MongoDB så kan du bädda in dokumenten. Så istället för att matcha din applikation mot en datamodell så kan du bygga en datamodell som matchar ditt användningsområde.

Med inbäddade dokument så kan du lagra relaterade data som du får tillgång till på samma ställe. När du utformar scheman för MongoDB så rekommenderas det att du bäddar in dokument som standard. Använd endast databas- eller applikationsspecifika joins och referenser när det är värt det.

Se till att arbetsbelastningen kan hämta ett dokument så ofta som det krävs. Samtidigt bör dokumentet även ha alla data som det behöver. Detta är avgörande för att din applikation ska få en exceptionell prestanda.

Nedan hittar du några olika mönster för att bädda in dokument:

Mönster för inbäddade dokument

Du kan använda detta för att även bädda in komplicerade understrukturer i de dokument som de används med. Genom att bädda in sammanhängande data i ett enda dokument så kan man minska antalet läsoperationer som behövs för att få fram data. Generellt sett så bör du strukturera ditt schema så att applikationen får all nödvändig information i en enda läshändelse. Regeln är därför att det som används tillsammans bör lagras tillsammans.

Mönster för inbäddad delmängd

Mönstret för inbäddad delmängd är ett hybridfall. Du använder detta för en separat samling av en lång lista med relaterade objekt, där du kan ha några av dessa objekt till hands för visning.

Här är ett exempel med en lista över filmrecensioner:

> 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"
}

Tänk dig tusen liknande recensioner, men du planerar att bara visa de två senaste när du visar en film. I det här scenariot så är det vettigt att lagra den delmängden som en lista 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"}   
  ]   
}

Enkelt uttryckt: om du regelbundet får tillgång till en delmängd av relaterade objekt, se till att du bäddar in den.

Oberoende åtkomst

Det kan hända att du vill lagra underdokument i sin egen samling för att skilja dem från den överordnade samlingen.

Ta exempelvis ett företags produktlinje. Om företaget säljer en liten uppsättning av produkter så vill man kanske lagra dem i företagsdokumentet. Men om man vill återanvända dem i flera företag eller komma åt dem direkt genom deras lagerhållningsenhet (SKU) så bör man även lagra dem i deras egen samling.

Om du manipulerar eller har tillgång till enheter som är oberoende av varandra så ska du skapa en samling för att lagra den separat för bästa praxis.

Obundna listor

Att lagra korta listor med relaterad information i deras dokument har en nackdel. Om din lista fortsätter att växa okontrollerat så bör du inte lägga den i ett enda dokument. Detta beror på att du inte skulle kunna stödja den särskilt länge.

Det finns två skäl till detta. För det första så har MongoDB en gräns för storleken på ett enskilt dokument. För det andra så kommer du att uppleva negativa resultat av en okontrollerad minnesanvändning om du får tillgång till dokumentet med för många frekvenser.

Enkelt uttryckt: Om en lista börjar att växa gränslöst så ska du göra en samling för att lagra den separat.

Utökat referensmönster

Det utökade referensmönstret är som undergruppsmönstret. Det optimerar även information som du regelbundet får tillgång till när det lagras på dokumentet.

Här utnyttjas det istället för en lista när ett dokument hänvisar till ett annat dokument som finns i samma samling. Samtidigt så lagras även vissa fält från det andra dokumentet för att man ska få tillgång till dem.

Till exempel:

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

Som du kan se så lagras ”the studio_id” så att du kan söka mer information om den studio som skapade filmen. Men studions namn kopieras även till detta dokument för enkelhetens skull.

Om du vill bädda in information från ändrade dokument regelbundet så ska du komma ihåg att uppdatera dokument där du har kopierat informationen när informationen ändras. Med andra ord, om du rutinmässigt får tillgång till vissa fält från ett dokument som det hänvisas till, bädda in dem.

Övervakning av MongoDB

Du kan använda övervakningsverktyg som Kinsta APM för att felsöka långa API-anrop, långsamma databasfrågor, långa externa webbadress-förfrågningar, för att nämna några exempel. Du kan även använda kommandon för att förbättra databasens prestanda. Utöver detta så kan du använda dem för att inspektera hälsan hos dina databasinstanser.

Varför bör du övervaka MongoDB-databaser?

En viktig aspekt av planeringen av databasadministrationen är att övervaka klustrets prestanda och hälsa. MongoDB Atlas hanterar majoriteten av administrationsarbetet genom sin förmåga till feltolerans/skalning.

Trots detta så måste användarna veta hur man följer kluster. De bör även veta hur de ska skala eller justera vad de behöver innan de drabbas av en kris.

Genom att övervaka MongoDB-databaser så kan du:

  • Observera utnyttjandet av resurserna.
  • Förstå den aktuella kapaciteten i din databas.
  • Reagera och upptäcka problem i realtid för att förbättra din applikationsstack.
  • Observera förekomsten av prestandaproblem och onormalt beteende.
  • Anpassa till kraven för styrning/dataskydd och servicenivåavtal (SLA).

Viktiga mätvärden att övervaka

När du övervakar MongoDB så finns det fyra viktiga aspekter som du måste tänka på:

MongoDB hårdvarumätvärden

Här är de viktigaste mätvärdena för övervakning av maskinvara:

Normaliserad process-CPU

Den definieras som den procentuella andel av tiden som CPU:n spenderar på tillämpningsprogramvara som underhåller MongoDB-processen.

Du kan skala detta till ett intervall på 0-100 % genom att dividera det med antalet CPU-kärnor. Detta inkluderar CPU som utnyttjas av moduler som kärnan och användaren.

En hög CPU för kärnan kan visa att CPU:n är uttömd genom operativsystemets operationer. Men användaren som är kopplad till MongoDB-verksamheten kan vara den grundläggande orsaken till CPU-utnyttjandet.

Normaliserad system-CPU

Det är den procentuella andel av tiden som CPU:n spenderade på systemanrop för att betjäna MongoDB-processen. Du kan skala den till ett intervall på 0-100 % genom att dividera den med antalet CPU-kärnor. Den täcker även den CPU som används av moduler som iowait, user, kernel, steal osv.

Användar-CPU eller hög kärna kan vara ett tecken på CPU-utmattning genom MongoDB-operationer (programvara). Hög iowait kan vara kopplad till att lagringskraften är uttömd och orsakar CPU-utmattning.

Disk IOPS

Disk IOPS är det genomsnittliga antalet förbrukade IO-operationer per sekund på MongoDB:s diskpartition.

Disk Latens

Detta är diskpartitionens läs- och skrivlatens i millisekunder i MongoDB. Höga värden (>500 ms) visar att lagringsarkivet kan påverka MongoDB:s prestanda.

Systemminne

Använd systemminne för att beskriva fysiska minnesbytes som används jämfört med tillgängligt ledigt utrymme.

Det tillgängliga mätvärdet ger en ungefärlig uppskattning av antalet byte av tillgängligt systemminne. Du kan använda detta för att köra nya applikationer, utan att byta ut något.

Fritt diskutrymme

Detta definieras som det totala antalet byte av fritt diskutrymme på MongoDB:s diskpartition. MongoDB Atlas erbjuder en automatisk skalning baserat på detta mätvärde.

Utbytesanvändning

Du kan använda ett diagram över swapanvändning för att beskriva hur mycket minne som placeras på swap-enheten. En hög användningsgrad i den här grafen visar att swap-minnet används. Detta visar att minnet är underförsörjt för den aktuella arbetsbelastningen.

MongoDB-klustrets anslutnings- och driftsmätningar

Här är de viktigaste mätvärdena för Operation och Anslutnings-mätvärden:

Utförandetider för operationer

Den genomsnittliga operationstiden (skriv- och läsoperationer) som utförs under den valda provperioden.

Opcounters

Det är den genomsnittliga hastigheten för utförda operationer per sekund under den valda provperioden. Grafen visar operationernas fördelning av operationstyper och hastighet för instansen.

Anslutningar

Detta mått avser antalet öppna anslutningar till instansen. Höga toppar eller siffror kan tyda på en icke-optimerad anslutningsstrategi, antingen från en server som inte svarar eller från klientsidan.

Målinriktning av förfrågningar och utförande av förfrågningar

Detta är den genomsnittliga hastigheten per sekund under den valda provperioden för skannade dokument. För de som utför sökningar så gäller detta under utvärdering av sökplaner och sökningar. Förfrågningsmålsättning visar förhållandet mellan antalet skannade dokument och antalet returnerade dokument.

Ett högt antal är ett tecken på icke-optimerade operationer. Dessa operationer skannar många dokument för att returnera en mindre del.

Skanning och beställning

Den beskriver den genomsnittliga hastigheten per sekund under den valda provperioden av förfrågningar. Den returnerar sorterade resultat som inte kan utföra sorteringsoperationen med hjälp av ett index.

Köer

Köer kan beskriva antalet operationer som väntar på en låsning, antingen skriv- eller läsoperationer. Stora köer kan vara ett tecken på att schemadesignen inte är optimal. Det kan även tyda på konfliktfyllda skrivvägar, vilket leder till en hög konkurrens om databasresurserna.

Mätvärden för replikering i MongoDB

Här är de primära mätvärdena för replikeringsövervakning:

Replication Oplog Window

Den här mätningen visar det ungefärliga antalet timmar som finns tillgängliga i den primära replikeringens oplog. Om en sekundär replikator släpar efter mer än det här beloppet så kan den inte hålla jämna steg och behöver en fullständig ny-synkronisering.

Replikeringsfördröjning

Replikeringsfördröjning definieras som det ungefärliga antalet sekunder som en sekundär nod ligger efter den primära i skrivoperationer. En hög replikeringsfördröjning tyder på att en sekundär nod har svårt att replikera. Detta kan påverka din verksamhets latenstid, med tanke på hur läs- och skrivrelaterade anslutningarna är.

Replikeringsutrymme

Det här mätvärdet avser skillnaden mellan den primära replikens oplogfönster och den sekundära replikfördröjningen. Om det här värdet går till noll så kan detta leda till att en sekundär replik går in i läget ÅTERUPPBYGGNAD.

Opcounters – repl

Opcounters – repl definieras som den genomsnittliga andelen replikeringsoperationer som utförs per sekund under den valda provperioden. Med opcounters – graph/metric så kan du ta en titt på operationshastigheten och fördelningen av operationstyper för den angivna instansen.

Oplog GB/timme

Detta definieras som det genomsnittliga antalet gigabyte oplog som primärsystemet genererar per timme. Stora oväntade volymer av oplog kan tyda på en mycket otillräcklig skrivarbetsbelastning eller ett problem med schemadesignen.

Verktyg för övervakning av MongoDB:s prestanda

MongoDB har inbyggda användargränssnittsverktyg i Cloud Manager, Atlas och Ops Manager för prestandaspårning. Det finns även några oberoende kommandon och verktyg för att titta på mer råbaserade data. Vi kommer att tala om några verktyg som du kan köra från en host som har tillgång och lämpliga roller för att kontrollera din miljö:

mongotop

Du kan utnyttja det här kommandot för att spåra hur mycket tid som en MongoDB-instans spenderar på att skriva och läsa data per samling. Använd följande syntax:

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

rs.status()

Det här kommandot returnerar statusen för replika-uppsättningen. Det utförs ur synvinkel för den medlem där metoden utförs.

mongostat

Du kan använda kommandot mongostat för att få en snabb överblick över statusen för din MongoDB-serverinstans. För optimal utdata så kan du använda det för att bevaka en enskild instans för en specifik händelse eftersom det ger en vy i realtid.

Använd det här kommandot för att övervaka grundläggande serverstatistik, t.ex. låsköer, uppdelning av operationer, minnesstatistik för MongoDB och anslutningar/nätverk:

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

dbStats

Det här kommandot returnerar lagringsstatistik för en specifik databas, t.ex. antalet index och deras storlek, total samlingsdata i förhållande till lagringsstorlek och samlingsrelaterad statistik (antal samlingar och dokument).

db.serverStatus()

Du kan använda kommandot db.serverStatus() för att få en överblick över databasens status. Detta ger dig ett dokument som representerar den aktuella instansens metriska räknare. Utför det här kommandot med jämna mellanrum för att sammanställa statistik om instansen.

collStats

Kommandot collStats samlar in statistik som liknar den som erbjuds av dbStats på samlingsnivå. Utmatningen består av ett antal objekt i samlingen, mängden diskutrymme som samlingen tar i anspråk, samlingens storlek och information om dess index för en viss samling.

Du kan använda alla dessa kommandon för att erbjuda rapportering och övervakning av databasservern i realtid som gör att du kan övervaka databasens prestanda och fel och hjälpa till med ett välinformerat beslutsfattande för att förfina en databas.

Hur man tar bort en MongoDB-databas

För att ta bort en databas som du skapat i MongoDB måste du ansluta till den via nyckelordet use.

Säg att du har skapat en databas som heter ”Engineers”. För att ansluta till databasen så använder du följande kommando:

use Engineers

Därefter skriver du db.dropDatabase() för att göra dig av med databasen. Efter utförandet så kan du förvänta dig följande resultat:

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

Du kan köra kommandot showdbs för att kontrollera om databasen fortfarande finns kvar.

Sammanfattning

För att få ut allt värde från MongoDB så måste du ha en god förståelse för grunderna. Det är därför centralt att ha en fullständig koll på MongoDB-databaser. Detta kräver att du först bekantar dig med metoderna för att skapa en databas.

I den här artikeln så belyser vi de olika metoderna som du kan använda för att skapa en databas i MongoDB, följt av en detaljerad beskrivning av några smarta MongoDB-kommandon för att hålla koll på dina databaser. Slutligen så avrundade vi diskussionen genom att diskutera hur du kan utnyttja inbäddade dokument och verktyg för prestandaövervakning i MongoDB för att se till att ditt arbetsflöde fungerar med högsta möjliga effektivitet.

Vad tycker du om dessa MongoDB-kommandon? Missade vi en aspekt eller metod som du skulle ha velat se här? Låt oss veta detta i kommentarerna!

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.