Angular Firestore在两个字段上的多个查询具有可观察性
我正在使用Angular和Firestore 我想在两个字段上执行对Firestore数据库的多重查询。现在可以使用Angular Firestore在两个字段上的多个查询具有可观察性,angular,google-cloud-firestore,Angular,Google Cloud Firestore,我正在使用Angular和Firestore 我想在两个字段上执行对Firestore数据库的多重查询。现在可以使用WHERE语句进行组合。 我的想法是组合这些值,然后向数据库发送请求。例如,我想回到所有的职位,城市是洛杉矶,旧金山,纽约和星级是5, 4。p> 因此,我必须对6种可能的组合进行查询: Where city = Los Angeles Where Stars = 5 …然后是下一个查询 Where city = Los Angeles Where stars = 4 Where
WHERE
语句进行组合。
我的想法是组合这些值,然后向数据库发送请求。例如,我想回到所有的职位,城市是洛杉矶,旧金山,纽约和星级是5, 4。p>
因此,我必须对6种可能的组合进行查询:
Where city = Los Angeles
Where Stars = 5
…然后是下一个查询
Where city = Los Angeles
Where stars = 4
Where city = San Francisco
Where Stars = 5
Where city = San Francisco
Where Stars = 4
…然后是下一个查询
Where city = Los Angeles
Where stars = 4
Where city = San Francisco
Where Stars = 5
Where city = San Francisco
Where Stars = 4
…然后是下一个查询
Where city = Los Angeles
Where stars = 4
Where city = San Francisco
Where Stars = 5
Where city = San Francisco
Where Stars = 4
等等
我知道如何对一个字段和一个值使用For
语句,就像您在下面的代码中看到的那样,但我不知道如何组合它们(在多个查询中对组合进行分组),然后等待所有执行(使用可观察项或主题)将它们分组到结果数组中。我在堆栈上找到了两个答案,但没有人真正帮助我做出正确的决定
这一个,但它只在一个领域,而不是观察
另一个
他们提出了“对查询中的一个字段执行过滤,对客户端代码中的另一个字段执行过滤”的好主意
如果结果很少,这个解决方案很好,但是如果结果很多,它会减慢过程,收回我们不需要的数据
export class AnnoncesListComponent implements OnInit {
queryParams: { departement:string, secteurAct:string };
subscriptionChange:Subscription;
annoncesSubscription:Subscription;
departementGet: any;
secteurActGet: any;
annonceQuery: Annonce[];
isFetchingData:boolean = false;
constructor(
private activeRoute : ActivatedRoute,
private annnonceService: AnnoncesService
) { }
ngOnInit() {
//Get QUERYPARAMS FROM THE URL
this.departementGet = decodeURIComponent(this.activeRoute.snapshot.queryParams['departement']);
this.secteurActGet = decodeURIComponent(this.activeRoute.snapshot.queryParams['secteurActivite']);
this.departementGet = this.departementGet.split('_B2-');
this.secteurActGet = this.secteurActGet.split('_B2-');
//FOR - TO QUERIES ALL THE DATA NEEDED - FIRST QUERY
for (var i = 0; i < this.secteurActGet.length; i++) {
this.annoncesSubscription = this.annnonceService.getAnnonces('secteurActivite', this.secteurActGet[i])
.subscribe( responseData => {
this.isFetchingData = false
this.annonceQuery = responseData.map(item => {
return {
id : item.payload.doc.id,
secteurAct : item.payload.doc.get('secteurActivite'),
departement : item.payload.doc.get('departement'),
region : item.payload.doc.get('region'),
description : item.payload.doc.get('description'),
infosClefs : item.payload.doc.get('name'),
} as Annonce;
})
console.log(this.annonceQuery);
});
//FOR - TO QUERIES ALL THE DATA NEEDED - SECOND QUERY
for (var i = 0; i < this.departementGet.length; i++) {
this.annoncesSubscription = this.annnonceService.getAnnonces('secteurActivite', this.departementGet[i])
.subscribe( responseData => {
this.isFetchingData = false
this.annonceQuery = responseData.map(item => {
return {
id : item.payload.doc.id,
secteurAct : item.payload.doc.get('secteurActivite'),
departement : item.payload.doc.get('departement'),
region : item.payload.doc.get('region'),
description : item.payload.doc.get('description'),
infosClefs : item.payload.doc.get('name'),
} as Annonce;
})
console.log(this.annonceQuery);
});
};
export类AnnoncesListComponent实现OnInit{
查询参数:{department:string,secteurAct:string};
subscriptionChange:订阅;
annoncesSubscription:订阅;
部门设置:任何;
部门行动:任何;
annonRequesty:Annonce[];
isFetchingData:boolean=false;
建造商(
专用activeRoute:ActivatedRoute,
专用ANNONCEService:ANNONCEService
) { }
恩戈尼尼特(){
//从URL获取查询参数
this.departmentGet=decodeURIComponent(this.activeRoute.snapshot.queryParams['department']);
this.secteuracget=decodeURIComponent(this.activeRoute.snapshot.queryParams['secteuractite']);
this.departmentget=this.departmentget.split(“'u B2-”);
this.secteuracget=this.secteuracget.split(“'u B2-”);
//FOR-TO查询所需的所有数据-第一次查询
for(var i=0;i{
this.isFetchingData=false
this.annonRequesty=responseData.map(项=>{
返回{
id:item.payload.doc.id,
secteurAct:item.payload.doc.get('secteuracite'),
部门:item.payload.doc.get('department'),
区域:item.payload.doc.get('region'),
描述:item.payload.doc.get('description'),
infosClefs:item.payload.doc.get('name'),
}曾经;
})
console.log(this.annonRequesty);
});
//FOR-TO查询所需的所有数据-第二次查询
for(var i=0;i{
this.isFetchingData=false
this.annonRequesty=responseData.map(项=>{
返回{
id:item.payload.doc.id,
secteurAct:item.payload.doc.get('secteuracite'),
部门:item.payload.doc.get('department'),
区域:item.payload.doc.get('region'),
描述:item.payload.doc.get('description'),
infosClefs:item.payload.doc.get('name'),
}曾经;
})
console.log(this.annonRequesty);
});
};
我的结果是两个独立的数据,没有组合,并且在每次迭代中创建一个可观察的数据。我认为使用rxjs/forkJoin处理多个并行请求是一个很好的方法 接受一个可观察的数组作为它的第一个参数,并返回一个可观察的数组,一旦所有传入的可观察的对象都完成,该数组将发出一个可观察的消息 我已经将您的代码重构为更易于阅读的代码,并利用forkJoin并行处理分支和扇区,然后输出每个结果数据的数组 如果您正在处理的数据量相当大,我甚至建议您考虑将cpu密集型操作拆分为多个线程,并避免阻塞主线程
// map array of departments into an array of Observables
const departmentsRequests = this.departementGet.map((departement) => {
return this.annnonceService.getAnnonces('departement', departement);
});
const secteurActiviteRequests = this.secteurActGet.map((secteur) => {
return this.annnonceService.getAnnonces('secteurActivite', secteur);
});
// forkJoin takes all Observables and emits once to its subscription
this.annoncesSubscription = forkJoin([
forkJoin(departmentsRequests),
forkJoin(secteurActiviteRequests),
]).subscribe(([departaments, secteurs]) => {
this.isFetchingData = false;
// all data has been loaded in parallel from firestore, handle it here
});
服务中用于获取数据的功能如下:
getAnnonces(champ, valeur){
return this.firestore.collection('annonce', ref => ref.where(champ, '==', valeur)).snapshotChanges();
}
我有you’s代码,但当我尝试输出结果时:
// forkJoin takes all Observables and emits once to its subscription
this.annoncesSubscription = forkJoin([
forkJoin(departmentsRequests),
forkJoin(secteurActiviteRequests),
]).subscribe(([departements, secteurs]) => {
this.isFetchingData = false;
// all data has been loaded in parallel from firestore, handle it here
console.log(departements);
});
没有结果。我尝试使用.get()而不是.snapshotChanges(),但他给了我一个[QuerySnapshot]非常感谢你宝贵的帮助。我将这样做以加入观察对象,然后使用两个值的组合(部门和部门)对结果进行排序。我想进行这种排序(组合)在查询中,但此解决方案看起来更简单。我将返回该解决方案并发布它是否工作,以获得我需要的结果。我无法在forkJoin之后获取数据。我尝试添加一个运算符以获取有效负载,但它在forkJoin之后似乎不工作,因为它在其他subscribe上工作,而没有对观察值进行分组.我在RXJS上找到了这门课程:我打算去上,因为在能够正确使用它之前,它真的需要对它的工作方式有一个坚实的了解。我不知道在forkJoin操作符之后如何取回有效负载…这是一门很棒的课程!我已经从Todd的座右铭中学习了所有这些课程,并且得到了充分的推荐ayload(结果数据)应该在传递给subscribe方法的回调中可用正在抛出错误,然后从未调用此回调。为什么?subscribe方法接受3个参数,所有这些参数都是回调:1.成功2.错误3.完成如果其中一个观测失败,它将执行错误回调。