sql >> Databasteknik >  >> NoSQL >> MongoDB

$vinda av ett objekt i aggregeringsramverk

Det är inte möjligt att göra den typ av beräkning som du beskriver med aggregeringsramverket - och det är inte eftersom det inte finns någon $unwind metod för icke-matriser. Även om person:value-objekten var dokument i en array, $unwind skulle inte hjälpa.

Funktionen "gruppa efter" (vare sig i MongoDB eller i någon relationsdatabas) görs på värdet av ett fält eller en kolumn. Vi grupperar efter fältvärde och summa/medelvärde/etc baserat på värdet på ett annat fält.

Enkelt exempel är en variant av det du föreslår, betygsfält som lagts till i exempelartikelsamlingen, men inte som en karta från användare till betyg utan som en array så här:

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

Nu kan du sammanställa detta med:

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

Men det här exemplet strukturerat som du beskriver det skulle se ut så här:

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

eller till och med detta:

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

Även om du kunde $unwind detta, det finns inget att sammanfatta här. Om du inte känner till hela listan över alla möjliga nycklar (användare) kan du inte göra mycket med detta. [*]

Ett analogt relationellt DB-schema till det du har skulle vara:

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

Det är inte vad som skulle göras, istället skulle vi göra det här:

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

och nu aggregerar vi med SQL:

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

Det finns en förbättringsbegäran för MongoDB som kan tillåta dig att göra detta i aggregeringsramverket i framtiden - förmågan att projicera värden till nycklar till vice versa. Samtidigt finns det alltid kartlägga/minska.

[*] Det finns ett komplicerat sätt att göra detta om du känner till alla unika nycklar (du kan hitta alla unika nycklar med en metod som liknar denna) men om du kan alla nycklar kan du lika gärna köra en sekvens av frågor av form db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1}) för varje användareX som kommer att returnera alla sina betyg och du kan summera och genomsnitta dem tillräckligt enkelt istället för att göra en mycket komplex projektion som aggregeringsramverket skulle kräva.



  1. Hur man får alla resultat om avkopplingsfältet inte finns i mongodb

  2. Hur byter jag namn på fält när jag utför sökning/projektion i MongoDB?

  3. In-memory cache med LRU-utgång

  4. Datamigreringar med Redis