Search code examples
angularrxjsngrxrxjs6ngrx-effects

RxJS groupBy on ngrx effects to observable custom array


I'm using ngrx effects to fetch data from an API. I've tried different combination of rxjs operators to achieve this. Currently using groupBy operator to acheive the following

API data:

projects = [{id: 1, name: project1, department: dept1, instance_count: 3},
{id: 2, name: project2, department: dept2, instance_count: 6},
{id: 3, name: project3, department: dept1, instance_count: 1},
{id: 1, name: project1, department: dept1, instance_count: 8}]

I have option to filter based on department. So the output when 'dept1' is selected should be

Result:

filteredProjects = [{id: 1, name: project1, department: dept1,   instance_count: 11 }, {id: 3, name: project3, department: dept1, instance_count: 1}] 

I've tried to use groupBy to group the data based on 'id' or 'department' and then apply filter and add the counts of the grouped data.

this.projects$: Observable<Project[]> = this._store.select(state => state.projects.allProjects)
  .map((projects: Project[]) => projects);

this.projects$.pipe(
groupBy(
project => project.id)
   ).subscribe(console.log);

I'm not able to get the groupBy and mergeMap working. Most of the examples I saw doesn't use pipe operator. This was throwing error ' Property 'id' does not exist on type 'Project[]'.


Solution

  • If i understand your desired output correctly, you can apply parts of this snippet to get what you want:

    test = [{id: 1, name: 'project1', department: 'dept1', instance_count: 3},
    {id: 2, name: 'project2', department: 'dept2', instance_count: 6},
    {id: 3, name: 'project3', department: 'dept1', instance_count: 1},
    {id: 1, name: 'project1', department: 'dept1', instance_count: 8}];
    
    constructor() {
        from(this.test).pipe(filter(a => a['department'] == 'dept1'), toArray()).subscribe(console.log);
    }
    

    console logged will be an array containing only the entries where department == 'dept1'

    EDIT1: (response to question: I need to apply groupBy based on ‘id’ after filtering)

    Using this snippet will give you two arrays of grouped results:

    from(this.test).pipe(filter(a => a['department'] == 'dept1'), groupBy(a => a.id), mergeMap(a => a.pipe(toArray()))).subscribe(console.log);