The groupBy
operator is one of RxJS's best kept secrets. In this lesson, you'll get an introduction to grouping data together by key. We'll use both hard-coded data and data coming from a server.
To dig deeper into groupBy, check out What GroupsBy in Vegas Stays in Vegas, the talk Mike Ryan and I gave at RxJS Live 2019.
Instructor: [00:00] We're using RxJS to create an observable of this array of to-do's here and just log them to the console. Unfortunately, we've got our user ID's all mixed up here. It'd be really nice if there was a way we could just group together these to-do's by the user ID.
[00:19] In fact, there is actually a way we could do this using something called the group by operator in RxJS. Let's just add the root by operator in a pipe here. What we're going to need to do is we're going to get an item and we're going to need to have a key selector. In our case we're going to use item.userID.
[00:42] Let's just type this to any and let's see what comes back there. You can see over in the console that we get this grouped observable and you can see we have a key here of one and a key of two corresponding to our user ID. Now we need to unwrap those Observables. What we're going to want to do is map each of these to an array. Let's do that.
[01:06] Let's do map and then we're going to get the group here and let's just do group.pipe and pass in the to array operator. Now this is part of the way there but you can see now we're getting two Observables. We need to merge all these down using mergeAll.
[01:24] Now you can see we get two arrays here. We get our array of user ID one and we get our array of user ID two. Now luckily, map followed by mergeAll is actually just the same thing as mergeMap so we can just change that to mergeMap and you can see we get the same result.
[01:44] Now we've got our todos grouped together by user ID. Awesome. What happens if we do this with data coming from a server though. I've got another todos here. Here we're calling a URL and we're getting todos and then we're returning the JSON response.
[02:03] First, let's just see what the response is here. I'm going to switch this to todosFetch and I'm just going to comment out this stuff. You can see that we get this big array that has 200 items in it but they're the same data structure. We've got out completed ID title and user ID.
[02:22] Will it work to just do the exact same thing that we did before? Well let's try it. Let's uncomment these lines here and try to group by user ID. You can see it's not what we want. We now get a nested array. We get an array of the array of 200 items.
[02:40] What's going on here? It turns out that we've got this from on our hard-coded data here and from is iterating each of these items sequentially whereas our fromFetch here is just returning the array.
[02:56] It's not an observable then. What's happening is RxJS is getting this to-do's list as a JavaScript array and groupBy is trying to run on an observable that doesn't actually have the key that we're looking for. Now we can solve this by transforming that array into an observable again and iterating each of those items separately.
[03:20] We can do this by mapping those data items to fromData. What's going to happen here is now we've got an observable so we'll need to merge those back down so that each of those observables becomes its own array. Now you can see we've got an array for user ID one and an array for user ID two etc., etc.
[03:42] Again, this map-and-merge-all is the same as just saying mergeMap and we still get the result that we want using groupBy.