如何在 Angularfire 中按动态对象属性进行过滤

How to filter by dynamic object properties in Angularfire

我在 Angular + AngularFire + Firestore 项目

中有如下模型
export interface Game {
    id: string;
    ... some other properties
    players: Array<{
       userId: string;
       name: string;
       picture: string;
    }>;
    playerIds: { [userId: string]: boolean };
}

数据看起来像这样

现在我想查询特定userId是玩家之一的所有记录。

因为我只想通过 userId(不是整个播放器对象)进行过滤,所以我不能使用 array-contain,所以我添加了一个 playerIds 属性 这是地图对象。

我的代码就像


    this.collection((ref) => ref.where(`playerIds.${user.id}`, '==', true).where(`status`, '!=', GameStatus.Started)).valueChanges(),

然后它要求我为这个查询创建一个索引。问题是索引是针对该用户的,并且包含该特定用户 ID。

在我在 nodejs 中使用 firebase 的其他项目中,我一遍又一遍地做同样的事情,但在 AngularFire 中似乎有所不同。

我知道如果我将它更改为用户 ID 数组,我可以通过 array-contains 查询,我的问题是为什么这不起作用以及如何使其起作用。

您的屏幕截图中的 playerIds 字段不是一个数组,而是一个包含键 bTr2...lnm4... 且值为 true 的映射。不幸的是,您需要为该地图中的每个字段创建一个单独的索引。

为了能够使用单个索引,将 playerIds 字段转换为实际数组:

playerIds: ["bTr2...", "lnm4..."]

有了这个结构,你:

  • 只需要一个索引,在playerIds字段上。
  • 可以用array-contains查询。
  • 可以使用 arrayUnion 向数组添加项目。
  • 使用 arrayRemove 从数组中删除项目。

另请参阅 updating elements in an array 上的文档。

尽管 Frank van Puffelen 的解决方案有效,但我发现了问题所在。

似乎如果我们有多个 whereorder 需要索引,问题是不可避免的。在我的例子中,我发现我应该在第二个 where 中使用 == 而不是 !=,当我更改它时,它不需要任何索引并且我能够像那样查询

ref.where(`playerIds.${user.id}`, '==', true).where(`status`, '==', GameStatus.Started)