首页 > 解决方案 > 将数组传递给 Firestore 数据库的 orderBy 子句有什么影响?

问题描述

想象一下,我的 Firestore 数据库中的文档代表食谱,每个文档都有一个“标签”字段,这是一个包含该食谱标签的数组(例如:辣味、法式、素食)。

当用户搜索一些标签时,我使用 array-contains-any 操作符来拉回所有包含至少一个用户搜索过的标签的食谱。然后,我按已匹配的标签数量对返回的文档进行排序。例如,如果用户搜索“香辣法国素食”,则“标签”字段包含所有这三个标签的文档首先出现,然后是“标签”字段包含其中两个标签的文档,等等。

我目前正在使用手动排序:

const userSearchedTags: string[] = [...] // array of tags searched for by user

recipes.sort((r1, r2) => {
  const r1Tags: string[] = r1.get('tags');
  const r2Tags: string[] = r2.get('tags');

  const r1TagMatchQuant = r1Tags.filter(r1Tag => userSearchedTags.includes(r1Tag)).length;
  const r2TagMatchQuant = r2Tags.filter(r2Tag => userSearchedTags.includes(r2Tag)).length;

  return r2TagMatchQuant - r1TagMatchQuant;
});

但是我想对这个查询进行分页,这要求它们由 Firebase 排序,所以我想我可以在查询中使用 orderBy 子句,以便 Firebase 将已经按匹配标签数量排序的文档返回给我。如果这可行,那么我将能够使用 startAfter() 子句对我的查询进行分页。我试过这个:

FirebaseFirestore.instance
  .collection('recipes')
  .where('tags', arrayContainsAny: userSearchedTags)
  .orderBy('tags')
  .get();

但它不返回按匹配标签数排序的文档。我认为它可能会返回按每个文档上的“标签”数组的长度排序的文档,但进一步的测试表明它也没有这样做。所以我的问题是,当我将“标签”(一个数组字段)传递给 orderBy 子句时,Firebase 如何对这些文档进行排序?

此外,有没有办法让 Firebase 按匹配标签的数量排序将文档返回给我,或者我现在这样做的方式(在拉回具有至少一个匹配标签的所有文档后手动排序)唯一的方法?

标签: fluttergoogle-cloud-firestore

解决方案


返回文档的顺序通常与文档出现在正在搜索的索引中的顺序相同。假设您的标签是字符串,那么根据数据类型的文档将是:

UTF-8 编码的字节顺序

所以我希望它是它匹配的第一个标签的顺序,而不是你希望的匹配标签的数量。这种基于计算值的结果优先级根本不是 Firestore 查询的目的,因为它需要 Firestore 在将匹配返回给您之前重新排序。


推荐阅读