问题
Struggling a bit too long here. I have two tables in Firebase:
accounts
LJHGGKJH
prop1: 'val'
prop2: 'val'
IUYIUTJF
prop1: 'val'
prop2: 'val'
locations_per_account
LJHGGKJH
0: [1, 5, 6]
IUYIUTJF
0: [5, 2, 8]
As you see accounts
item's unique key points to locations_per_account
item's unique key - if they match they belongs to the same user.
Now I want to make one method in my service which would provide me observable of every account and its locations, so I could use async
pipe in my template and extract the data.
Here I get all accounts:
getAllAccounts() {
return this.afDb.list('accounts/', {
query: {
orderByChild: 'hasAccount',
equalTo: true
}
})
}
Here I get locations of particular account:
getAccountLocations(optionalUid : string) {
let uid : any;
this.authService.authInfo$.subscribe(val => uid = val.$uid);
if (typeof optionalUid === 'undefined')
return this.afDb.object('locations-per-account/' + uid);
return this.afDb.object('locations-per-account/' + optionalUid);
}
So I need to merge these streams into one and by merging I should construct the new shape of returning object.
(the order of both tables is symmetric (if thats the right word), but I am not sure if it will stay the same in the future, so i would like to check if both keys match).
Also to note - as you see, I could add locations array to every account, but I do it in separate table because I try to make my Firebase database as flat as possible, to avoid things like "Full table scan". Please advice if any thoughts - I am pretty new in building databases.
回答1:
Use forkJoin to wait for both queries, then map the two sets together on id:
Rx.Observable.forkJoin([accounts$, locations$]).subscribe(results => {
const [accounts, locations] = results
const joined = accounts.map(account => {
return {
id: account.id,
prop1: account.prop1,
prop2: account.prop2,
locations: locations.filter(location => location.id === account.id)[0].loc };
})
console.log(joined);
});
This presumes that Firebase is emitting a single value for each query, each of which is an array (which I think it does, from the docs).
Also presumes one account and location per id, if not then the mapping would need to get more complicated.
Here's a CodePen which simulates the scenario. CodePen
回答2:
so in your case, the pseudo code could look like this:
Observable.forkJoin([this.getAllAccounts(), this.getAccountLocations()])
.subscribe(results => {
console.log(results)
}
);
a couple articles on managing observables: Cory Rylan, Tor
来源:https://stackoverflow.com/questions/46529904/angular-firebase-merge-two-observables-into-one