Hoe gegevens in MongoDB te relateren?

Ik bewaar een tekenreeks in een database samen met de eigenaren van de tekenreeks (een of meer eigenaren per tekenreeks).

Ik heb altijd met MySQL gewerkt, wat een conventionele relationele database is. In dat geval zou ik de string samen met een unieke id in een tabel opslaan, en vervolgens de unieke id van de string samen met de eigenaren (als meerdere records) in een tweede tabel.

Ik kan vervolgens strings van eigenaren ophalen met behulp van een SQL Join.

Ik ben nu bezig met een project met MongoDB en ik doe hetzelfde als hierboven.

Zou dit als verkeerd worden beschouwd bij het werken met NoSQL-databases? Moet ik niet denken in termen van 'relaties' wanneer ik met NoSQL werk?

Een andere manier om hetzelfde te bereiken in MongoDB is het op deze manier op te slaan:

{
    "string": "foobar",
    "owners": [
        "owner1",
        "owner2",
        "owner3"
    ]
}

In dit geval ben ik echter niet zeker hoe ik zou zoeken naar 'alle strings die eigendom zijn van owner1'.

6
Gebruik alstublieft "NoSQL" niet als een paraplu. Je gebruikt MongoDB. Dat is het. "NoSQL" betekent te veel en te weinig :-)
toegevoegd de auteur user166390, de bron

4 antwoord

Zou dit niet de juiste manier zijn om met NoSQL-databases te werken? Moet ik niet denken in termen van 'relaties' bij het werken met NoSQL?

Er zijn zoveel vragen over het geval van inbedding en dat komt zo weinig voor.

Sommige dingen die hier niet zijn genoemd, moeten worden overwogen als u wilt insluiten:

  • Zal de documentgrootte enorm toenemen? Als dit het geval is, kan het document vaak op schijf worden verplaatst, dit is een slechte zaak.
  • Zal de gerelateerde rij veel join hebben in de verzameling waar ik aan werk (d.w.z. video kan gebruiker niet insluiten). Als dit het geval is, kunt u problemen krijgen bij het kopiëren van overtollige gegevens van de gerelateerde rij naar het subdocument, vooral bij het bijwerken van die overtollige gegevens.
  • Hoe moet ik deze resultaten weergeven?

Het weergeven van de resultaten is altijd een beslissende factor bij het al dan niet insluiten. Als u een groot aantal rijen moet pagineren, bijvoorbeeld 1000, moet u de operator $ slice gebruiken in normale query's of in het aggregatieraamwerk. Bij 1000 geef ik toe dat het vrij snel kan zijn, maar vroeg of laat zal de werking in het geheugen langzamer zijn dan bij normale bevraging (eigenlijk zou dit altijd moeten zijn).

Als u complexe sortering en weergave van de subdocumenten nodig hebt, kunt u deze opsplitsen en in plaats daarvan de documentstructuur hebben van:

{
    "string": "foobar",
    "owners": [
        ObjectId(),
        ObjectId(),
        ObjectId()
    ]
}

Ik denk dat dit in feite een meer performante structuur is voor uw gegevens, omdat de eigenaar klinkt als een rij < gebruiker in een gebruikers -collectie.

In plaats van de subdocumenten te vullen met mogelijk veranderende gegevens van de gebruiker, kunt u gewoon verwijzen naar hun _id . Dit is behoorlijk kool omdat je de relatie kunt verankeren, maar tegelijkertijd zal het document maar heel weinig groeien, wat hopelijk een lage kans op constante schijfbeweging betekent, niet alleen dat, maar een kleinere werkset die in totaal een meer performante operatie creëert. Niet alleen dat, maar natuurlijk zal de _id van een eigenaar zelden veranderen, dus de enige bewerkingen die u waarschijnlijk zult moeten uitvoeren op deze subset van gegevens is maken en verwijderen.

Teruggaan naar complexe sortering en paginering. Met deze gegevens kunt u natuurlijk alle eigenaar id's met een enkele heen-en-terugreis krijgen en dan kunt u in een andere retourronde naar die eigenaarsrijen in de gebruikers tabel zoeken met normale query's met behulp van een $ in zorgt voor de complexe weergave die u nodig hebt.

Dus deze structuur die ik heb gevonden, is zeer performant.

Of course this structure depends on your querying, it might be better to instead house the string id on the user but in this case it doesn't since a user presumably can own many strings as such I would say it is a many->many relationship embedded on the string side.

Hopelijk helpt dit en ben ik niet in cirkels rondgegaan,

6
toegevoegd

Om het antwoord van dbaseman aan te vullen:

Ja, je aanpak lijkt goed. U kunt eenvoudig zoeken naar "alle strings die eigendom zijn van owner1"

db.collection.find({owners: 'author1'})

Dit is mogelijk omdat mongodb arrays op een speciale manier behandelt.

5
toegevoegd
Bedankt voor het tonen van een voorbeeld van de vraag.
toegevoegd de auteur xbonez, de bron

When dealing with embedded data I'd recommend getting to familiar with the Atomicity behaviour in mongo. A good starting point would be here : http://docs.mongodb.org/manual/core/data-modeling/#atomicity

In uw specifieke geval bij het toevoegen/verwijderen van een gebruiker ObjectId (zoals aanbevolen door Sammaye) aan uw array "owners", wilt u een findAndModify() -bewerking op het tekenreeksdocument om ervoor te zorgen dat wanneer veel naar dat document wordt geschreven, de gegevensintegriteit nog steeds wordt gehandhaafd.

In deze operatie raad ik aan de volgende operators te gebruiken:

  1. Als u een eigenaar toevoegt, $ addToSet om duplicaten te voorkomen
  2. Bij het verwijderen van een eigenaar, $ pull

Both are documented here: http://docs.mongodb.org/manual/reference/operators/#update-operators-array

3
toegevoegd

Dit lijkt op de juiste aanpak; Onthoud echter dat het altijd afhankelijk is van de totaliteit van uw project, wat de doelen zijn (prestaties, flexibiliteit), welke query's u het hardst wilt uitvoeren, of u ad-hoc-query's moet uitvoeren en andere factoren. Over het algemeen is het gebruik van geneste documenten, zoals u schreef, echter het juiste alternatief voor het gebruik van joins en externe sleutels.

Houd ook rekening met de maximale documentgrootte (momenteel 16 MB), die wees bezorgd als er veel (zoals honderdduizenden) eigenaren van een bepaalde string zijn.

2
toegevoegd
Dank je. Ik hoef me geen zorgen te maken over de maximale documentgrootte, omdat ik er niet in de buurt kom. Mijn meest voorkomende query zijn inserts. Heel, heel weinig vondsten.
toegevoegd de auteur xbonez, de bron