MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Grupowanie dokumentów w MongoDB na specjalnych warunkach

Zastrzeżenie

Zanim przeczytasz resztę odpowiedzi, przeczytaj https://docs. mongodb.com/manual/core/aggregation-pipeline-limits/ Oczekuje się, że wynikowy dokument w pytaniu będzie zawierał tablicę wszystkich dokumentów należących do określonej grupy wiekowej.Rozmiar tej tablicy nie może przekraczać 16 MB , więc poniższy kod będzie działał tylko dla bardzo małych kolekcji małych dokumentów.

Kod:

db.collection.aggregate([
    { $sort: { age: 1 } },
    { $group: {
            _id: null,
            ages: { $push: "$age" }
    } },
    { $addFields: {
        ranges: { $reduce: { 
            input: { $range: [ 1, { $size: "$ages" }, 1 ] }, 
            initialValue: [ [ { $arrayElemAt: [ "$ages", 0 ] } ] ], 
            in: { $cond: { 
                if:  { $gt: [
                    { $subtract: [ { $arrayElemAt: [ "$ages", "$$this" ] }, { $arrayElemAt: [ "$ages", { $subtract: [ "$$this", 1 ] } ] } ] },
                    2
                    ] }, 
                then: { $concatArrays: [ "$$value",  [ [ { $arrayElemAt: [ "$ages", "$$this" ] } ] ] ] }, 
                else: { $concatArrays: [ 
                    { $slice: [ "$$value" , { $subtract: [ { $size: "$$value" }, 1 ] } ] },
                    [ { $concatArrays: [ 
                        { $arrayElemAt: [ { $slice: [ "$$value" , -1 ] }, 0 ] }  ,  
                        [ { $arrayElemAt: [ "$ages", "$$this" ] } ]
                    ]  } ]
                ] }
            } }
        } } 
    } },
    { $unwind: "$ranges" }, 
    { $lookup: {
       from: "collection",
       localField: "ranges",
       foreignField: "age",
       as: "group"
     } },
     { $project: { _id: 0, group: 1 } }
])

Część, która może wymagać nieco wyjaśnienia, to sposób obliczania grup wiekowych.

W tym celu pobieramy wszystkie grupy wiekowe za pomocą $group w jedną tablicę, a następnie $addFields „zakresy” – tablica 2D grup wiekowych z przerwami między najstarszą osobą w młodszej grupie a najmłodszą osobą w starszej grupie jest większa niż 2 lata.

Tablica jest obliczana przy użyciu $reduce $range tablica indeksów wszystkich grup wiekowych, z wyjątkiem pierwszego, który przechodzi do wartości początkowej.

Wyrażenie redukujące to $cond która oblicza różnicę między obecnym a poprzednim ($subtract ) element tablicy wszystkich grup wiekowych.

Jeśli jest większy niż 2, nowa grupa wiekowa jest dodawana przy użyciu $concatArrays . W przeciwnym razie wiek jest dodawany do najstarszej grupy za pomocą $slice aby wypchnąć do ostatniej grupy w tablicy zakresów i $setUnion aby wyeliminować duplikaty.

Podczas obliczania grup wiekowych $lookup tę samą kolekcję według wieku, aby pogrupować je w tablicy "group".




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jackson nie może zdeserializować obiektu MongoDB przekazanego przez REST

  2. Znajdź zduplikowane rekordy w MongoDB

  3. Baza danych DIY w chmurze w usługach internetowych Amazon — nowy dokument

  4. Jak rzutować tylko pasujące pola tablicy zagnieżdżonej w zapytaniu powłoki mongo?

  5. Wybierz pasujący element tablicy i zwróć wybrane pola