我在尝试构建的Angular 6 cli / TS / AngularFire中使用以下模型。我是所有这些东西的新手。
export class Book {
constructor(
public id: string,
public title: string,
public genres: any[]
) {}
}
我希望能够使用AngularFire2查找与Firebase的Cloud Firestore中存储的类型相匹配的所有图书。
标准查询如下所示(documentation):
afs.collection('books', ref => ref.where('size', '==', 'large'))
理想情况下,我想打电话给Firebase,因为它不会获取集合中的所有文档,所以效率更高(如果我的想法错误,请告诉我)。例如,这样的东西。
afs.collection('books', ref => ref.where(book.genres.containsAny(array of user defined genres)));
我对NoSQL数据建模的了解有限,但是如果有更有效的方法可以快速处理1000、30,000甚至100,000个文档,那么我会很乐意更改模型。
现在我正在这样做。
filterArray = ["Genetic Engineering", "Science Fiction"];
filteredBooks: Book[] = [];
ngOnInit() {
this.db.collection<Book>('books')
.valueChanges().subscribe(books => {
for (var i=0; i < books.length; i++) {
if (books[i].genres.some(v => this.filterArray.includes(v))) {
this.filteredBooks.push(books[i]);
}
}
});
}
这可以过滤文档,但是在速度和可伸缩性方面是否有更有效的方法(仅获取匹配的文档而不是全部)?
答案 0 :(得分:0)
您应该先限制文档。您不想提取3万个文档,然后过滤它们。而且您走在正确的道路上,但是格式不正确。您想做这样的事情:
afs.collection<book>('books', ref => ref.where('genres', 'array-contains', genre)
我认为,截至目前,您不能传递类似以下的数组:
afs.collection<book>('books', ref => ref.where('genres', 'array-contains', genres) // note that genres is plural implying a list of genres
但是,最好在各个类型之间进行for循环,并为每个类型提取一次图书清单,然后再将其串联起来。
现在,您提到您还想建议以其他方式存储数据。我建议您不要将数组用于类型。而是将其制作为地图(基本上是一个对象),如下所示:
author: string;
title: string;
...
genres: map
然后您可以执行以下操作:
author: 'Herman Melville'
title: 'Moby Dick'
...
genres: {
'classics': true
'nautical': true
}
然后您可以像这样过滤集合:
afs.collection<book>('books', ref => ref.where('genres.classics', '==', true).where('genres.nautical', '==' true)
我希望这对您有帮助