RxJs groupBy 多條件分組

前言

在Angular或Nest.Js中,使用groupBy分組資料相當方便
但應該是在Nest.Js使用到的機會最多XD

畢竟前端通常都是接到處理完的結果了,只需要渲染頁面就好

作法

比如下列資料,只需以shopId分組

const array = [
    {id: 1, shopId: 'a', category: 'AAA', name: 'Andy', birth: '1990/06/25'}, 
    {id: 2, shopId: 'b', category: 'BBB', name: 'Ben', birth: '1989/01/01'},
    {id: 3, shopId: 'a', category: 'AXX', name: 'Amy', birth: '1990/06/01'},
    {id: 4, shopId: 'b',  category: 'BXX', name: 'Brandon', birth: '1989/05/06'},
    {id: 5, shopId: 'a',  category: 'AAA', name: 'Anderson', birth: '1991/12/06'},
];

from(array).pipe(
    groupBy(val => val.shopId),
    mergeMap(group => group.pipe(toArray())
);

// 得到結果如下:
[
    [
        {id: 1, shopId: 'a', category: 'AAA', name: 'Andy', birth: '1990/06/25'}, 
        {id: 3, shopId: 'a', category: 'AXX', name: 'Amy', birth: '1990/06/01'},
        {id: 5, shopId: 'a',  category: 'AAA', name: 'Anderson', birth: '1991/12/06'},
    ], 
    [
        {id: 2, shopId: 'b', category: 'BBB', name: 'Ben', birth: '1989/01/01'},
        {id: 4, shopId: 'b', category: 'BXX', name: 'Brandon', birth: '1989/05/06'}
    ]
]

但若想要多條件,依shopId + category當主鍵來分類
很遺憾不能在groupBy無腦的寫成groupBy(val => {shopId: val.shopId, category: val.category}),

後來在stack overflow(參考資料裡)查到解法

他的寫法摻了不少花括號,猛一看一瞬間還以為要寫的很複雜
但其實就是多一個mergeMap,裡面再做一次groupBy就好了!

以上述範例需求:依shopId + category當主鍵來分類
精簡後如下

from(array).pipe(
    groupBy(val => val.shopId),
    mergeMap(group => group.pipe(toArray()),
    mergeMap((_array) =>
      from(_array).pipe(
        groupBy(val => val.category), // 第2個分組條件
        mergeMap(group => group.pipe(toArray())),
      )
    ),
    // 後面繼續串接所須的業務邏輯
);

// 得到結果如下:
[
    [
        {id: 1, shopId: 'a', category: 'AAA', name: 'Andy', birth: '1990/06/25'}, 
        {id: 5, shopId: 'a',  category: 'AAA', name: 'Anderson', birth: '1991/12/06'},
    ], 
    [
        {id: 3, shopId: 'a', category: 'AXX', name: 'Amy', birth: '1990/06/01'},
    ],
    [
        {id: 2, shopId: 'b', category: 'BBB', name: 'Ben', birth: '1989/01/01'},
        {id: 4, shopId: 'b', category: 'BXX', name: 'Brandon', birth: '1989/05/06'}
    ]
]

若還有第三、第四個分組條件
依樣畫葫蘆繼續接mergeMap

參考資料

stack overflow / How to groupby by two fields from array using rxjs?