使用rxjs的顺序查询和相关查询

时间:2016-11-23 08:55:57

标签: angular rxjs angularfire2

我尝试在Firebase数据库上进行多个顺序和相关查询。 这就是数据库的样子:

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

我想要检索所有书籍,遍历它们,获取相关的作者姓名,在每个书籍对象中设置值并返回包含书籍对象的Observable数组。

我试过这种方式:

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;
        });
}

但这只会返回第一本书。

2 个答案:

答案 0 :(得分:0)

鉴于list(/books)返回类似[bookObj, bookObj]的数组,您需要获取每本书的作者信息,不需要concatMap,除非输出需要保存输入书籍。

  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; 
        }
      );
  }

答案 1 :(得分:0)

由于无法使用运算符实现此功能,我创建了import UIKit import Alamofire import SVProgressHUD struct postinput { let mainImage : UIImage! let name : String! let author : String! let summary : String! let content : String! } class TableViewController: UITableViewController { //var activityIndicatorView: UIActivityIndicatorView! var postsinput = [postinput]() var refresh = UIRefreshControl() var mainURL = "https://www.example.com/api" typealias JSONstandard = [String : AnyObject] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.tableView.addSubview(refresh) //;refresh.attributedTitle = NSAttributedString(string: "Refreshing...", attributes:[NSForegroundColorAttributeName : UIColor.black]) refresh.backgroundColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0) //refresh.tintColor = UIColor.white refresh.addTarget(self, action: #selector(self.refreshData), for: UIControlEvents.valueChanged) //refresh.addTarget(self, action: #selector(getter: TableViewController.refresh), for: UIControlEvents.valueChanged) refresh.attributedTitle = NSAttributedString(string: "Updated: \(NSDate())") //activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) //tableView.backgroundView = activityIndicatorView callAlamo(url: mainURL) } func refreshData() { Alamofire.request("https://www.example.com/api").responseJSON(completionHandler: { response in self.parseData(JSONData: response.data!) self.tableView.separatorStyle = UITableViewCellSeparatorStyle.singleLine DispatchQueue.main.async { self.tableView.reloadData() self.refresh.endRefreshing() } }) } func callAlamo(url : String){ //activityIndicatorView.startAnimating() SVProgressHUD.show(withStatus: "Loading...") SVProgressHUD.setDefaultStyle(SVProgressHUDStyle.dark) SVProgressHUD.setDefaultAnimationType(SVProgressHUDAnimationType.native) SVProgressHUD.setDefaultMaskType(SVProgressHUDMaskType.black) Alamofire.request(url).responseJSON(completionHandler: { response in self.parseData(JSONData: response.data!) self.tableView.separatorStyle = UITableViewCellSeparatorStyle.singleLine //self.activityIndicatorView.stopAnimating() SVProgressHUD.dismiss() }) } func parseData(JSONData : Data) { do { var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard // print(readableJSON) if let posts = readableJSON["posts"] as? [JSONstandard] { for post in posts { let title = post["title"] as! String let author = post["author"] as! String guard let dic = post["summary"] as? [String: Any], let summary = dic["value"] as? String else { return } let str = summary.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil) print(str) guard let dic1 = post["content"] as? [String: Any], let content = dic1["value"] as? String else { return } let str1 = content.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil) print(str1) //print(author) if let imageUrl = post["image"] as? String { let mainImageURL = URL(string: imageUrl ) let mainImageData = NSData(contentsOf: mainImageURL!) let mainImage = UIImage(data: mainImageData as! Data) postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary, content: content)) } } DispatchQueue.main.async { self.tableView.reloadData() } } } catch { print(error) } } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return postsinput.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell") // cell?.textLabel?.text = titles[indexPath.row] let mainImageView = cell?.viewWithTag(2) as! UIImageView mainImageView.image = postsinput[indexPath.row].mainImage mainImageView.layer.cornerRadius = 5.0 mainImageView.clipsToBounds = true //(cell?.viewWithTag(2) as! UIImageView).image = postsinput[indexPath.row].mainImage let mainLabel = cell?.viewWithTag(1) as! UILabel mainLabel.text = postsinput[indexPath.row].name mainLabel.font = UIFont.boldSystemFont(ofSize: 18) mainLabel.sizeToFit() mainLabel.numberOfLines = 0; let autLabel = cell?.viewWithTag(3) as! UILabel autLabel.text = postsinput[indexPath.row].author autLabel.font = UIFont(name: "Helvetica", size:16) autLabel.textColor = UIColor(red: 0.8784, green: 0, blue: 0.1373, alpha: 1.0) /* #e00023 */ let sumLabel = cell?.viewWithTag(4) as! UILabel sumLabel.text = (postsinput[indexPath.row].summary).replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil) sumLabel.font = UIFont(name: "Helvetica", size:16) sumLabel.textColor = UIColor(red:0.27, green:0.27, blue:0.27, alpha:1.0) //let contentLabel = cell?.viewWithTag(0) as! UILabel //contentLabel.text = (postsinput[indexPath.row].content).replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil) //(cell?.viewWithTag(3) as! UILabel).text = postsinput[indexPath.row].author return cell! } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { postsinput.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) } else if editingStyle == .insert { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } via Observable方法并在返回新数组之前执行查询:

create()

这不是我的预期,但它有效。