CombinedFilter Observable for QueryFirebase的唯一键

CombinedFilter Observable for QueryFirebase的唯一键

问题描述:

我正在开发一个应用程序,其中承包商可以说他们在特定日期“可用”,并且每个承包商都有一个“位置”。雇主可以根据地点和可用性搜索可用性。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方式。

谁能帮助?谢谢!

这是我的解决方案。我相信有更好的方法来做到这一点。更新:下面更好的解决方案。

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

    }); 

}