AngularFire2查询集合,用于有效地在数组中具有值的文档

时间:2018-08-03 15:41:09

标签: google-cloud-firestore angularfire2

我在尝试构建的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]);
         }
       }
    });
 }

这可以过滤文档,但是在速度和可伸缩性方面是否有更有效的方法(仅获取匹配的文档而不是全部)?

1 个答案:

答案 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)

我希望这对您有帮助