首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用rxfire和rxjs (OR查询)连接两个Firestore查询

如何使用rxfire和rxjs (OR查询)连接两个Firestore查询
EN

Stack Overflow用户
提问于 2018-11-16 00:50:06
回答 1查看 2.2K关注 0票数 4

目标很简单:使用rxjsrxfirernfirebase来连接两个防火墙查询。

我读过关于连接查询的多个教程12,但是它们都失败了,错误也不一样。

代码语言:javascript
复制
//Simple test for collectionData
import { collectionData } from 'rxfire/firestore';

this.myQuery = this.props.docRef.collection(`messages`).where('read', 'array-contains', this.props.me.uid)
collectionData(this.myQuery, 'id').subscribe(docs => console.log(docs))
//Fails with error: this._next is not a function.

或者,

代码语言:javascript
复制
this.publicQuery = this.props.docRef.collection('messages').where('public', '==', true) 
this.myQuery = this.props.docRef.collection(`messages`).where('read', 'array-contains', this.props.me.uid)
const myQuery$ = new Rx.Subject();
const publicQuery$ = new Rx.Subject();
this.myQuery.onSnapshot((querySnapshot) => {
    myQuery$.next(querySnapshot.docs.map(d => d.data()  ));
});
this.publicQuery.onSnapshot((querySnapshot) => {
    publicQuery$.next(querySnapshot.docs.map(d => d.data()  ));
});
const orQuery$ = combineLatest(this.myQuery, this.publicQuery).switchMap((docs) => {
    var [one, two] = docs;
    var combined = one.concat(two);
    return Rx.Observable.of(combined);
})
orQuery$.subscribe((result) => {
    console.log('>>>> ', result)
})
//TypeError: undefined is not a function (near ...switchMap)

如何成功地连接两个防火墙查询(OR)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-27 09:59:11

你已经离解决方案很近了。让我们一步一步地讨论这些问题。

首先,不需要仅仅为了从Subject转换结果而创建一个onSnapshot。而不是这样:

代码语言:javascript
复制
this.myQuery.onSnapshot((querySnapshot) => {
    myQuery$.next(querySnapshot.docs.map(d => d.data()))
});

我们可以使用“可管道转换运算符”实现同样的目标:

代码语言:javascript
复制
const myQuery$ = this.myQuery.onSnapshot.pipe(
    map(querySnapshot => querySnapshot.docs.map(d => d.data()))
);

对于另一个查询也是如此:

代码语言:javascript
复制
const publicQuery$ = this.publicQuery.onSnapshot.pipe(
    map(querySnapshot => querySnapshot.docs.map(d => d.data())
);

其次,要连接这两个查询,combineLatest确实是正确的创建函数。

但是,使用更新的RxJS版本可能会导致错误,该版本不再支持“fluent”运算符(正式称为“补丁操作员”)。从RxJS 6开始,它们已经被“管道运营商”所取代。例如,myObs$.map(...)已经变成了myObs$.pipe(map(...))。教程可能使用RxJS的旧版本,其中第一个版本仍然是可能的。

此外,如果内部可观察到的只是一个switchMap运算符,那么就不应该使用of。在这种情况下,使用map操作符就足够了,它的行为将是相同的。

使用新的RxJS 6+语法和map,组合如下所示:

代码语言:javascript
复制
const orQuery$ = combineLatest(myQuery$, publicQuery$).pipe(
    map(([one, two]) => one.concat(two))
)

其余的代码应该是正确的。

侧注:要记住,与您在SQL中的代码等价的是UNION (而不是JOIN)。为了编程地实现JOIN,您需要将结果集A的每个对象与结果集B的每个对象组合起来,并为每一对对象创建一个连接对象。这样一个用于无键OUTER JOIN的函数如下所示(放置在您的map管道中):

代码语言:javascript
复制
one.map(a => 
   two.map(b => Object.assign({}, a, b)))
.reduce((p, c) => p.concat(c), [])

如果您想要一个没有重复对象的UNION,那么只连接来自two的那些在list one中没有匹配的主键的项。这是您的映射功能:

代码语言:javascript
复制
one.concat(two.filter(twoItem => !one.some(oneItem => oneItem.id == twoItem.id)))

演示:一个完整的工作演示,上面的代码和一个模拟的FireStore可以在这里找到:

https://stackblitz.com/edit/rxjs-mefynu?devtoolsheight=60

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53329908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档