我正在开发一款基于 Firestore 的社交应用程序,用户可以在其中查看帖子的新闻源。提要包括:
(sourcePrivacyStatus === PUBLIC)
。(newsfeedType === NEWS_FEED)
。(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
};
这种方法面临的挑战
我正在寻找一种经济有效且高效的方法来实现此功能。
不是直接答案,而是不同的方法。
我们在 Firestore 中的复杂查询也遇到了类似的问题。因此,我们最终将相关集合同步到 ElasticSearch 服务,该服务在查询、排序和聚合结果方面绝对非常出色。
我们使用ElasticSearch来查询:
我们使用 Firestore 完成其余所有操作,特别是单个实体的“详细信息页面”,我们可以在其中订阅所需的特定单个文档,并在前端获取实时更新。用户喜欢这样。
为了简化和保护客户端的 ElasticSearch 集成,我们设置了
onCall
Firebase 函数,它充当我们 ElasticSearch 服务的代理。
为了将文档同步到 ElasticSearch,我们在所需的集合上设置了一个
onDocumentWritten()
触发器,确保同步时使用版本控制。
我想您也可以使用 BigQuery 做同样的事情。它声称也可以处理非结构化数据,但我还没有尝试过。
关于:
Firestore 有一个限制,即 in 运算符最多可以处理 10 个值
in
操作员限制已提高到 30。这并不是说它对您的问题有帮助,但您要知道,它可以同时为您节省一些查询。
如果您决定坚持使用 Firestore
in
运营商,您可以限制为 30 个最相关的关注用户。
为此,每次关注用户 (B) 执行相关操作时,您都需要更新关注用户 (A),无论“相关”对您的服务意味着什么。
例如,每次用户 B 撰写帖子时,都会更新用户 A 关注列表中用户 B 条目的时间戳。然后,用户 A 可以根据最近的活动过滤其关注列表,并通过
in
运算符仅使用这 30 个列表。