sql >> Database >  >> NoSQL >> MongoDB

$wind een object af in het aggregatieraamwerk

Het is niet mogelijk om het type berekening uit te voeren dat u beschrijft met het aggregatieraamwerk - en het is niet omdat er geen $unwind . is methode voor niet-arrays. Zelfs als de person:value-objecten documenten in een array waren, $unwind zou niet helpen.

De functionaliteit "groeperen op" (in MongoDB of in een relationele database) wordt gedaan op de waarde van een veld of kolom. We groeperen op waarde van veld en som/gemiddelde/etc op basis van de waarde van een ander veld.

Eenvoudig voorbeeld is een variant van wat u voorstelt, beoordelingsveld toegevoegd aan de voorbeeldartikelverzameling, maar niet als een kaart van gebruiker naar beoordeling, maar als een array zoals deze:

{ title : title of article", ...
  ratings: [
         { voter: "user1", score: 5 },
         { voter: "user2", score: 8 },
         { voter: "user3", score: 7 }
  ]
}

Nu kunt u dit samenvoegen met:

[ {$unwind: "$ratings"},
  {$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } } 
]

Maar dit voorbeeld, gestructureerd zoals u het beschrijft, ziet er als volgt uit:

{ title : title of article", ...
  ratings: {
         user1: 5,
         user2: 8,
         user3: 7
  }
}

of zelfs dit:

{ title : title of article", ...
  ratings: [
         { user1: 5 },
         { user2: 8 },
         { user3: 7 }
  ]
}

Zelfs als je zou kunnen $unwind dit, er valt hier niets te verzamelen. Tenzij u de volledige lijst van alle mogelijke sleutels (gebruikers) kent, kunt u hier niet veel mee doen. [*]

Een analoog relationeel DB-schema voor wat je hebt zou zijn:

CREATE TABLE T (
   user1: integer,
   user2: integer,
   user3: integer
   ...
);

Dat is niet wat we zouden doen, in plaats daarvan zouden we dit doen:

CREATE TABLE T (
   username: varchar(32),
   score: integer
);

en nu aggregeren we met behulp van SQL:

select username, avg(score) from T group by username;

Er is een verbeteringsverzoek voor MongoDB waarmee u dit in de toekomst in het aggregatieraamwerk kunt doen - de mogelijkheid om waarden naar sleutels te projecteren naar vice versa. Ondertussen is er altijd een kaart/verkleining.

[*] Er is een ingewikkelde manier om dit te doen als u alle unieke sleutels kent (u kunt alle unieke sleutels vinden met een soortgelijke methode) maar als u alle sleutels kent, kunt u net zo goed een reeks query's van de form db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1}) voor elke userX die al hun beoordelingen retourneert en u kunt ze eenvoudig genoeg optellen en middelen in plaats van een zeer complexe projectie uit te voeren die het aggregatieraamwerk zou vereisen.



  1. MongoDB $ifNull

  2. 2 manieren om een ​​verzameling in MongoDB te verwijderen

  3. Hoe kan ik de momenteel geverifieerde gebruiker-principal krijgen met lentebeveiliging en Redis in de lente-opstarttoepassing?

  4. phpredis-extensie werkt niet, kan 'redis.so' niet laden