sql >> Database >  >> NoSQL >> MongoDB

MongoDB kaart/verminderen over meerdere collecties?

Een reduceerfunctie mag één keer worden aangeroepen, met een toets en alle bijbehorende waarden (maar alleen als er meerdere waarden voor de sleutel zijn - deze wordt helemaal niet aangeroepen als er maar 1 waarde voor de sleutel is).

Het kan ook meerdere keren worden aangeroepen, telkens met een sleutel en alleen een subset van de bijbehorende waarden , en de vorige reduceerresultaten voor die sleutel. Dit scenario heet een re-reduce . Om re-reduces te ondersteunen, moet je reduceerfunctie idempotent zijn.

Er zijn twee belangrijke kenmerken in een idempotent-reductiefunctie:

  • De retourwaarde van de reduceerfunctie moet in het dezelfde formaat zijn als de waarden it takes in. Dus als je reduce-functie een array van strings accepteert, zou de functie een string moeten retourneren. Als het objecten met meerdere eigenschappen accepteert, zou het een object moeten retourneren met dezelfde eigenschappen. Dit zorgt ervoor dat de functie niet breekt wanneer deze wordt aangeroepen met het resultaat van een eerdere reductie.
  • Maak geen aannames op basis van het aantal waarden it takes in. Het is niet gegarandeerd dat de values parameter bevat alles de waarden voor de opgegeven sleutel. Dus met behulp van values.length in berekeningen is zeer riskant en moet worden vermeden.

Bijwerken: De twee onderstaande stappen zijn niet vereist (of zelfs mogelijk, ik heb het niet gecontroleerd) op de meer recente MongoDB-releases. Het kan nu deze stappen voor u uitvoeren, als u een uitvoerverzameling opgeeft in de opties voor het verkleinen van de kaart:

{ out: { reduce: "tempResult" } }

Als je reduceerfunctie idempotent is, zou je geen problemen moeten hebben om meerdere collecties in kaart te brengen. Verklein gewoon de resultaten van elke verzameling:

Stap 1

Voer de kaartverkleining uit op elke vereiste verzameling en sla de resultaten op in een enkele, tijdelijke verzameling. U kunt de resultaten opslaan met behulp van een afrondingsfunctie:

finalize = function (key, value) {
  db.tempResult.save({ _id: key, value: value });
}

db.someCollection.mapReduce(map, reduce, { finalize: finalize })
db.anotherCollection.mapReduce(map, reduce, { finalize: finalize })

Stap 2

Voer nog een kaartverkleining uit op de tijdelijke verzameling, met dezelfde functie voor verkleinen . De kaartfunctie is een eenvoudige functie die de sleutels en waarden uit de tijdelijke verzameling selecteert:

map = function () {
  emit(this._id, this.value);
}

db.tempResult.mapReduce(map, reduce)

Deze tweede kaartverkleining is in feite een herverkleining en zou u de gewenste resultaten moeten geven.



  1. Basis HORLOGE doen met StackExchange.Redis

  2. Mongoose.js instance.save() callback wordt niet geactiveerd

  3. Batch set data van Dictionary naar Redis

  4. Mongo Query met Regex in Node JS werkend OP EEN VARIABELE