如何动态链接Firebase中的条件,而不预先知道要设置多少条件

时间:2019-04-12 03:39:12

标签: javascript angular firebase google-cloud-firestore

我正在使用Firebase在Angular中工作。

我想创建一个函数,该函数将接收两个参数字符串和对象,并根据动态地根据来自特定集合的对象键值对返回一个经过过滤的数据的Observable。

例如,当我用这种方式称呼它时,我期望得到这样的结果:

dynamicFilter('users',{name: 'Jack', age: 30})

它应该评估此呼叫:

firebase.collection('users',ref => ref.where('name','==','Jack').where('age','==',30))

所以我可以订阅它:

dynamicFilter('users',{name: 'Jack', age:30}).subscribe(res => {
    console.log(res)
})

我希望函数是通用的,因为我事先不知道将通过该对象传递多少条件。

我尝试过:

constructor(private db: AngularFirestore){}

dynamicFilter(collectionName: string, options: object){

    let targetCollection = this.db.firestore.collection(collectionName)
    let query;
    let keys = Object.keys(options)

    for(let i = 0; i < keys.length; i++ ){
        if(i === 0){
            query = targetCollection.where(keys[i],'==',options[keys[i]])
        }else{
            query = query.where(keys[i],'==',options[keys[i]])
        }
    }
    return query
}

那么该返回值怎么办?它是Query类的实例,我想我可以调用方法get,该方法返回一个像query.get().then(res => console.log(res))的promise。 但是resQuerySnapshot类的另一个实例。我怎样才能简单地获取数据?

2 个答案:

答案 0 :(得分:0)

要从QuerySnapshot获取数据:

querySnapshot.forEach(function(doc) {
  console.log(doc.data());
});

所以:

dynamicFilter('users',{name: 'Jack', age:30}).subscribe(querySnapshot => {
    querySnapshot.forEach(function(doc) {
      console.log(doc.data());
    });
})

有关此的更多信息,请参见:

答案 1 :(得分:0)

我一直在搜索您可以想象的所有资源,最后摆脱了它,开始自己进行实验,它已经完成,它可以完美运行,甚至您都不需要订阅它,它会通过Callback功能。

用例:

1。您在服务中编写了以下代码,以使内容保持清晰和可重复使用。

例如,我们称它为DataService

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';

@Injectable({
  providedIn: 'root'
})

export class DataService {

constructor(private fire: AngularFirestore) { }

dynamicQueryFilter(collectionName: string, options: object, callbackFn: Function): void{

    const bindedCallback: Function = callbackFn.bind(this)

    const targetCollection = this.fire.collection(collectionName).ref
    const optionPairs = Object.entries(options)

    let queryMap = targetCollection.where(optionPairs[0][0],'==',optionPairs[0][1])

    optionPairs.slice(1).forEach(item => {
       queryMap = queryMap.where(item[0],'==',item[1])
    })

    queryMap.get()
      .then(resolve => {
        const documents = []
        resolve.forEach(doc => documents.push(doc.data()))
        bindedCallback(documents)
      })
}

2。然后将其注入您的组件中

export class AppComponent implements OnInit {

    constructor(private db: DataService){}

    users: User[];

    ngOnInit(){
        this.db.dynamicQueryFilter
           (
            'users',
            {name: 'Jack', age: 30, profession: 'Programmer', isMaried: true},
            (res) => this.product = res
           )
    }

}

3。渲染所有已婚的程序员,他们的名字叫杰克(Jack),并且在模板中年满30岁

<div *ngIf="users">
    <div *ngFor="let user of users">
        <h2>{{user.name}} {{user.surname}}</h2>
        <hr>
        <h4>Additional Info</h4>
        <div><b>Age: </b>{{user.age}}</div>
        <div><b>Profession: </b>{{user.profession}}</div>
        <div><b>Adress: </b>{{user.adress}}</div>
        <div><b>Phone: </b>{{user.phone}}</div>
        //and so on....
    </div>
</div>

使用此工具,您可以动态地进行任何过滤。

您可以将dynamicQueryFilter的参数绑定到模板中的输入或任何形式,并让用户执行交互式实时多重过滤。

特别感谢Frank Van Puffelen分享他的知识。