高效查询 Firestore 中具有大量关注用户列表的新闻源以降低成本

问题描述 投票:0回答:1

我正在开发一款基于 Firestore 的社交应用程序,用户可以在其中查看帖子的新闻源。提要包括:

  1. 公开帖子
    (sourcePrivacyStatus === PUBLIC)
  2. 新闻源类型帖子
    (newsfeedType === NEWS_FEED)
  3. 仅关注者发布的帖子
    (sourcePrivacyStatus === FOLLOWERS_ONLY)
    如果创建者 (added_by) 位于用户的关注列表中。

问题 要查询仅限关注者的帖子,我使用

in
运算符将
added_by
与关注的用户 ID 列表 (
followedIds
) 进行匹配。但是,Firestore 有一个限制,即 in 运算符最多可以处理 10 个值。

如果用户关注数百或数千个用户,则需要将 followId 拆分为 10 个块并运行多个查询。例如:

对于 1000 个关注的 ID,我需要 100 个查询。 这显着增加了读取成本和查询执行时间。

当前方法 以下是我目前处理查询的方式:

const chunkArray = (array: any[], chunkSize: number) => {
  const chunks = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    chunks.push(array.slice(i, i + chunkSize));
  }
  return chunks;
};

export const retrieveFollowedNewsfeedsQuery = async (
  followedIds: string[],
  lastTimeStamp: FirebaseFirestore.Timestamp | null = null,
  limit: number = 20
) => {
  const idChunks = chunkArray(followedIds, 10); // Split IDs into chunks of 10
  const queries = idChunks.map((ids) => {
    let query = db
      .collection("newsfeed")
      .where(
        Filter.or(
          Filter.where("sourcePrivacyStatus", "==", CoffeeStatus.PUBLIC),
          Filter.where("newsfeedType", "==", NewsfeedTypes.NEWS_FEED),
          Filter.and(
            Filter.where("sourcePrivacyStatus", "==", CoffeeStatus.FOLLOWERS_ONLY),
            Filter.where("added_by", "in", ids)
          )
        )
      )
      .orderBy("timeStamp", "desc");

    if (lastTimeStamp) {
      query = query.startAfter(lastTimeStamp);
    }

    return query;
  });

  const results = [];
  for (const query of queries) {
    const snapshot = await query.get();
    snapshot.forEach((doc) => {
      results.push({ id: doc.id, ...doc.data() });
    });
  }

  results.sort((a, b) => b.timeStamp.toMillis() - a.timeStamp.toMillis());
  return results.slice(0, limit); // Return only the required number of results
};

这种方法面临的挑战

  1. 高成本:对大型关注者列表运行 100 多个查询会导致高读取成本。
  2. 效率低下:对多个查询的结果进行排序和合并会增加延迟。
  3. 速率限制:Firestore 具有速率限制,许多并发查询可能会超出该速率限制。

我正在寻找一种经济有效且高效的方法来实现此功能。

node.js google-cloud-firestore nosql backend query-optimization
1个回答
0
投票

不是直接答案,而是不同的方法。

我们在 Firestore 中的复杂查询也遇到了类似的问题。因此,我们最终将相关集合同步到 ElasticSearch 服务,该服务在查询、排序和聚合结果方面绝对非常出色。

我们使用ElasticSearch来查询:

  • 仪表板,包含大量聚合数据。
  • 列表,用户可以在其中选择不同的过滤器和排序。动态选择筛选列表的属性需要 Firestore 创建所有可能的组合,这不仅不切实际,而且会消耗大量资源。

我们使用 Firestore 完成其余所有操作,特别是单个实体的“详细信息页面”,我们可以在其中订阅所需的特定单个文档,并在前端获取实时更新。用户喜欢这样。

为了简化和保护客户端的 ElasticSearch 集成,我们设置了

onCall
Firebase 函数,它充当我们 ElasticSearch 服务的代理。

为了将文档同步到 ElasticSearch,我们在所需的集合上设置了一个

onDocumentWritten()
触发器,确保同步时使用版本控制。

我想您也可以使用 BigQuery 做同样的事情。它声称也可以处理非结构化数据,但我还没有尝试过。

关于:

Firestore 有一个限制,即 in 运算符最多可以处理 10 个值

in
操作员限制已提高到 30。这并不是说它对您的问题有帮助,但您要知道,它可以同时为您节省一些查询。

如果您决定坚持使用 Firestore

in
运营商,您可以限制为 30 个最相关的关注用户。 为此,每次关注用户 (B) 执行相关操作时,您都需要更新关注用户 (A),无论“相关”对您的服务意味着什么。

例如,每次用户 B 撰写帖子时,都会更新用户 A 关注列表中用户 B 条目的时间戳。然后,用户 A 可以根据最近的活动过滤其关注列表,并通过

in
运算符仅使用这 30 个列表。

© www.soinside.com 2019 - 2024. All rights reserved.