1

I'm trying to make multiple sequential and dependent queries on a Firebase database. This is how the database look like :

books : { book1: { title: 'Book 1', author: 'author1' } }
authors: { author1: { name: 'Author 1' } }

I'd like to retrieve all the books, iterate through them, get the related author name, set the value in each book object and return an Observable array containing the book objects.

I tried this way :

getBooks(): Observable<Book[]> {
    return this._af.database
        .list('/books')
        .flatMap(e => e)
        .concatMap(e => this.getAuthor(e.author), (a, b) => {
            a.author = b.lastName;
            return a;
        });
}

But this returns the first book only.

7
  • Use mergeMap() (alias flatMap()) Commented Nov 23, 2016 at 8:58
  • Can you be more specific? I tried to use flatMap(), concatMap(), mergeMap(), etc. but, apparently, I don't know how to use them. Commented Nov 23, 2016 at 10:02
  • Can you be more specific? ;-) Please edit the question and post the code that demonstrates what you try to accomplish, what you tried and where you failed. Commented Nov 23, 2016 at 10:03
  • @untemps One of these answers could help you stackoverflow.com/questions/40170157/… stackoverflow.com/questions/40346728/… stackoverflow.com/questions/40250882/… Commented Nov 23, 2016 at 13:36
  • @martin That's sound promissing, thank you. Commented Nov 23, 2016 at 13:39

2 Answers 2

0

Given that list(/books) returns an array like [bookObj, bookObj] you would need to fetch the author information of each book, no need for concatMap unless order preservation of your input books is required for the output.

  getBooks(): Observable<Book[]> {
    return this._af.database
      .list('/books')
      .flatMap(booksArr => Rx.Observable.from(booksArr))
      .flatMap(
        book => this.getAuthor(e.author),
        (book,a) => { 
          a.author = book.lastName; 
          return a; 
        }
      );
  }
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks but that actually doesn't work since books is an array with no flatMap method.
ahh, if list('/books') returns a vanilla array then you need to convert it to an observable using flatMap(booksArr => Rx.Observable.from(booksArr)) so all the books are emitted as events on the observable stream.
0

Being unable to achieve this using operators, I have created an Observable via create() method and perform the queries before returning a new array :

getBooks(): Observable<Book[]> {
    return Observable.create(observer => {
        const res: Book[] = [];
        this._af.database
            .list('/books').subscribe(books => {
            books.map(book => {
                this.getAuthor(book.author).subscribe(author => {
                    res.push(
                        new Book(book.$key, book.title, author.lastName, book.price, book.image)
                    );
                    if (res.length === books.length) {
                        observer.next(res);
                    }
                })
            });
        });
    });
}

That's not what I expected but it works.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.