2017-03-09 35 views
0

我正在開發一個應用程序,其中承包商可以說他們在特定日期「可用」,並且每個承包商都有一個「位置」。僱主可以根據地點和可用性搜索可用性。CombinedFilter Observable for QueryFirebase的唯一鍵

該位置基於GeoFire。這將返回可用承包商的$ key。

,看起來像這樣:

geoQueryContractor(radius, lat, lng) { 

    const subject = new Subject(); 

    this.fbGeoRef = firebase.database().ref('geofire') 

    this.geoFire = new GeoFire(this.fbGeoRef); 

    this.geoFire.ref(); 

    this.geoQuery = this.geoFire.query({ 
     center: [lat, lng], 
     radius: radius 
    }); 

    this.geoQuery.on("key_entered", function(key, location, distance) { 
     subject.next(key); 
    }); 

    return subject.asObservable(); 

} 

接下來,我可以通過搜索,看起來像這樣的火力節點獲得可用性 「/ AvailForContractor/$ {時間戳}/$ UID:真正的」

這是如何工作,它返回他們的個人資料:

getAvailablitybyContractor(timestamp) { 

    const availContractorKeys$ = this.db.list(`/AvailForContractor/${timestamp}`); 

    const AvailContractors$ = availContractorKeys$ 

     //maping each key 
     .map(keysPerContractor => keysPerContractor 

     //once we have each key, we can map it and create an fb object observable 
     .map(keyPerContractor => this.db.object(`/users/${keyPerContractor.$key}`))) 

     //now we got back an array of firebase object observables (fbojs) and we need to combine them in to one observable 
     .mergeMap(fbojs => Observable.combineLatest(fbojs)) 
     .do(console.log) 

    AvailContractors$.subscribe(); 
} 

我有這2個互相獨立工作。我真的需要知道在第二個函數中返回的所有$ key,哪些在第一個函數中可用。我只需要返回符合這兩條標準的配置文件。

我一直在與CombineLatest,mergeMap,withLatestFrom和Filter搞亂,但我無法弄清楚如何以正確的方式做到這一點。

我的想法是,一旦我從第2個功能拿到鑰匙,與GeoFire觀察到的結合起來,並過濾獨特的鍵,然後執行此部分:

//once we have each key, we can map it and create an fb object observable 
    .map(keyPerContractor => this.db.object(`/users/${keyPerContractor.$key}`))) 

    //now we got back an array of firebase object observables (fbojs) and we need to combine them in to one observable 
    .mergeMap(fbojs => Observable.combineLatest(fbojs)) 
    .do(console.log) 

這是不完整的,但一個貧窮的嘗試。 ..

getAvailablitybyContractor(timestamp, radius, lat, lng) { 

    const availContractorKeys$ = this.db.list(`/AvailForContractor/${timestamp}`); 

    //when we get back the keys, we are going to switch to another obeservables 
    const AvailContractors$ = availContractorKeys$ 

     //maping each key 
     .map(keysPerContractor => keysPerContractor 
      .map(keyPerContractor => keyPerContractor.$key)) 
      .combineLatest(this.geoQueryContractor(radius, lat, lng)) 

      // .withLatestFrom(this.geoQueryContractor(radius, lat, lng), (keysPerContractor, geo) => ([keysPerContractor, geo])) 
      //once we have each key, we can map it and create an fb object observable 

     //  .map(keyPerContractor => this.db.object(`/users/${keyPerContractor.$key}`))) 
     // //now we got back an array of firebase object observables (fbojs) and we need to combine them in to one observable 
     // .mergeMap(fbojs => Observable.combineLatest(fbojs)) 

     .do(console.log) 

    AvailContractors$.subscribe(); 
} 

GeoFire踢出這樣各個鍵的方式:

3vAWWHaxHRZ94tc8yY08CH3QNQy3H74INXgYWIMrUcAtZloFGkwJ6Qd2

火力地堡會踢出來的按鍵陣列:

[3vAWWHaxHRZ94tc8yY08CH3QNQy3, H74INXgYWIMrUcAtZloFGkwJ6Qd2, J9DHhg5VQrMpNyAN8ElCWyMWh8i2, fdZYKqqiL0bSVF66zGjBhQVu9Hf1 ] 

最終結果將是那些獨特的組合中,我會用得到的配置文件的RX方式。

誰能幫助?謝謝!

回答

0

這是我的解決方案。我相信有更好的方法來做到這一點。更新:下面更好的解決方案。

static geoArray: Array<string> = []; 

constructor(private af: AngularFire, private db: AngularFireDatabase) { 

} 

getAvailablitybyContractor(timestamp, radius, lat, lng) { 

    const availContractorKeys$ = this.db.list(`/AvailForContractor/${timestamp}`); 

    const AvailContractors$ = availContractorKeys$ 

     //maping each key 
     .map(keysPerContractor => keysPerContractor.map(keyPerContractor => keyPerContractor.$key) 
     .filter(key => ContractorService.geoArray.indexOf(key) > -1) 

     //once we have each key, we can map it and create an fb object observable 
     .map(keyPerContractor => this.db.object(`/users/${keyPerContractor}`))) 

     //now we got back an array of firebase object observables (fbojs) and we need to combine them in to one observable 
     .mergeMap(fbojs => Observable.combineLatest(fbojs)) 
     .do(console.log) 

    AvailContractors$.subscribe(); 
} 

geoQueryContractor(radius, lat, lng) { 


    this.fbGeoRef = firebase.database().ref('geofire') 

    this.geoFire = new GeoFire(this.fbGeoRef); 

    this.geoFire.ref(); 

    this.geoQuery = this.geoFire.query({ 
     center: [lat, lng], 
     radius: radius 
    }); 

    this.geoQuery.on("key_entered", function(key, location, distance) { 

     ContractorService.geoArray.push(key); 

    }); 

} 


} 

該解決方案好得多。上面的那個真的是越野車。它必須清除數組。在一天結束時,我將不得不執行搜索2x以獲得正確的結果。不能接受的。

這是一個更好的方法,它更具反應性,它沒有上面的錯誤。我確信有更好的方法來折射這個或改進它。

getAvailablitybyContractor(timestamp) { 

    let availContractorKeys$ = this.db.list(`/AvailForContractor/${timestamp}`); 

    this.AvailContractors$ = availContractorKeys$ 

     //maping each key 
     .map(keysPerContractor => keysPerContractor.map(keyPerContractor => keyPerContractor.$key)) 
     //Combine observable from GeoQuery 
     .combineLatest(this.keys$, (fb, geo) => ([fb, geo])) 
     // fb, geo are accessible individually 
     // .filter method creates a new array with all elements that pass the test implemented by the provided function 
     // key is now iteriable through geo.indexOf 
     .map(([fb, geo]) => { 
      return fb.filter(key => geo.indexOf(key) > -1) 
     }) 
     .map(filteredKeys => filteredKeys.map(keyPerContractor => this.db.object(`/users/${keyPerContractor}`))) 
     //now we got back an array of firebase object observables (fbojs) and we need to combine them in to one observable 
     .mergeMap(fbojs => { 
      return Observable.combineLatest(fbojs) 
     }) 
     .do(console.log) 

} 

getGeoQuery(radius, lat, lng) { 

    this.geoQuery = this.geoFire.query({ 
     center: [lat, lng], 
     radius: radius 
    }); 

} 

geoQueryContractor() { 

    return this.keys$ = Observable.create(observer => { 

     var keys = new Array(); 

     this.geoQuery.on("key_entered", (key, location, distance) => { 
      keys.push(key); 
      observer.next(keys); 
     }); 

    }); 

}