我有一个主题事件模型-定义了它应该具有的属性:
export class EventSchema {
title: string;
start: string;
end: string;
price: number;
constructor(title: string, start: string, end: string, price: number){
this.title=title;
this.start=start;
this.end=end;
this.price=price;
}
}
我还有一个封装上述模型的模型-在一个数组中有一个主题名称和事件属性,因为单个主题可以有多个事件:
import { EventSchema } from './eventSchema.model';
export class SubjectEvents {
subjectName: string;
eventData: EventSchema[];
constructor(subjectName: string, eventData: EventSchema[]){
this.subjectName=subjectName;
this.eventData=eventData;
}
}
我在firebase中有一个与这些模型匹配的集合。到目前为止,只有两份文档,一份涉及数学科目,一份涉及物理科目,每份涉及2个事件。示例数据是:
我有此服务,它获取数据并对其进行转换。在这种情况下,我想将一个主题(文档)的每个事件放入一个大数组中。也许我需要合并每个文档的输出...不确定如何。我能够在某种程度上实现这一目标-但结果重复出现,我不明白为什么。请在下面查看最终输出的屏幕截图。
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument, QuerySnapshot, QueryDocumentSnapshot } from 'angularfire2/firestore';
import { Observable, of, Subscription } from 'rxjs';
import { map, filter } from 'rxjs/operators';
import 'rxjs/add/operator/mergeMap';
import { SubjectEvents } from '../_models/subjects/subjectEvents.model';
import { EventSchema } from '../_models/subjects/eventSchema.model';
@Injectable()
export class SubjectEventsService {
subjectEventCollection : AngularFirestoreCollection<SubjectEvents>;
subjectEventDocument : AngularFirestoreDocument<SubjectEvents>;
subjectEvents : Observable<SubjectEvents[]>;
subjectEvent : Observable<SubjectEvents>;
filteredArr : Observable<any[]>;
constructor(private afs : AngularFirestore) {
//Get user collection on initialise
this.subjectEventCollection = this.afs.collection('subjectEvents');
}
getSubjectEvents(subjectFilter: string): Observable<SubjectEvents[]> {
this.filteredArr = this.subjectEventCollection.snapshotChanges()
.pipe(map(changes => {
let filteredArr : any = [];
console.log(filteredArr);
return changes
.map(action => {
console.log(action);
const data = action.payload.doc.data() as SubjectEvents;
data.subjectName = action.payload.doc.data().subjectName;
data.eventData = action.payload.doc.data().eventData;
console.log(data);
data.eventData.forEach(result => {filteredArr.push(result); console.log(filteredArr)});
return filteredArr;
});
}));
return this.filteredArr;
}
}
答案 0 :(得分:0)
我希望我能帮上忙,这是我的建议:使用filter
和map
,但是在过滤器中通过自定义函数来达到您的预期结果:
const duplicateData = from(data);
const emmited = [];
const hasBeenEmitted = (item, emmited) => {
if (emmited.filter(e => e.title !== item.title).length === 0) {
emmited.push(item);
return item;
} else {
return null;
}
};
const source = duplicateData.pipe(
filter(item => hasBeenEmitted(item, emmited)),
map(e => ({ value: e.price, start: e.start }))
);
source.subscribe(console.log);
答案 1 :(得分:0)
我提供了一个更好的方法,我创建了一个名为hasBeenEmitted
的自定义运算符,您只需要向其提供要过滤数据的属性即可。
const duplicateData = from(data);
const hasBeenEmitted = n => source =>
new Observable(observer => {
const emmited = [];
return source.subscribe({
next(item) {
if (emmited.filter(e => e.title !== item.title).length === 0) {
emmited.push(item);
observer.next(item);
}
},
error(err) { observer.error(err); },
complete() { observer.complete(); }
})
});
const source = duplicateData.pipe(
hasBeenEmitted(item => item.title),
map(e => ({ value: e.price, start: e.start }))
);
source.subscribe(console.log);