【问题标题】:Firebase Limits One "array-contains-any" per query - what do to if I need multiple?Firebase 限制每个查询一个“array-contains-any” - 如果我需要多个怎么办?
【发布时间】:2020-02-06 23:21:07
【问题描述】:

如问题所述,Firebase 每个查询仅允许一个数组包含任意 (https://firebase.google.com/docs/firestore/query-data/queries)。

当有人需要复杂查询时会发生什么?我的查询需要大约 10 个 .where() 和 4 个 array-contains-any 子句。是否有解决方法,或者我必须从第一个 array-contains-any 中获取结果,然后一次又一次地标注?似乎很费力而且没有必要。

var usersMatchesCollection = config.db.collection("Users");
var currentUserMatchesAllData = usersMatchesCollection.where('preferences.lookingFor', 'array-contains-any', docDataPreferences.lookingFor)
.where('info.identifyAs', '==', docDataPreferences.prefIdentifyAs)
.where('info.languages', 'array-contains-any', docDataPreferences.prefLanguages) 
.where('age', 'array-contains-any', docDataPreferences.ageRange) 
.where('profession', 'array-contains-any', docDataPreferences.prefProfession) 
.where('education', '==', docDataPreferences.prefEducation) 
.where('kids', '==', docDataPreferences.prefKids) 
.where('married', '==', docDataPreferences.prefMarried) 
.where('drinking', '==', docDataPreferences.prefDrinking) 
.where('smokingCig', '==', docDataPreferences.prefSmokingCig) 
await currentUserMatchesAllData.get().then( function (matchesQuerySnapshot) {
  matchesQuerySnapshot.forEach(function(doc) {
      console.log('doc data: ' + JSON.stringify(doc.data().id));
  })
})

【问题讨论】:

  • 看起来您可能对 Firestore 的查询功能提出了一些要求。如果您无法对数据进行建模,以便在考虑到限制的情况下对其进行查询,那么您可能必须按照您所指出的那样进行多次查询。
  • 如果您想将其发布为答案,我可以让它与此评论一起使用。不幸的是,没有一种不那么费力的查询方式,希望有人会看到这一点并让我们知道另一种方式!

标签: firebase react-native google-cloud-firestore


【解决方案1】:

您要求的是 Cloud Firestore 无法提供的查询,因为我们无法以通用的方式进行,无论数据如何都可以扩展。您可以使用一些技巧来降低查询的复杂性,这意味着减少您需要分解的查询数量。

preferences.lookingFor

对于where('preferences.lookingFor', 'array-contains-any', docDataPreferences.lookingFor) 条件,假设可能的不同值是有限的并且总数是已知的,您可以创建一个可能性映射并将其简化为一个等式。例如,

让我们假设 3 个可能的值 ABC,并且您必须至少有 1 个。这意味着只有 7 个不同的查询变体,可能是编码为一系列布尔字段:

preferences.lookingForCheck = {
    A: <if A>,
    B: <If B>,
    C: <If C>,
    AB: <if A OR B>,
    AC: <If A OR C>,
    BC: <If B OR C>,
    ABC: <if A OR B OR C>,
} 

这些在写入时计算起来相当简单,这意味着您可以轻松计算要查询的字段:where('preferences.lookingForCheck.BC', '==', true)

信息.语言

这一个可能是为了扩展想要组合爆炸,所以让我们保留这个。

年龄

我会过度简化,并假设一些简单的桶,所以:21-3031-4445-6465+。您可以像上面那样创建显式字段(A、B、C、D),这将是 15 个字段。如果您可以假设范围是连续的(例如,如果选择了 21-30 & '45-64',则必须选择 31-30),您可以通过说有 2 个用户来自的值列表来进行更多优化必须从每个中选择一个,并且第二个中的值必须等于或大于第二个: lower_age: [21, 31, 45, 65+] upper_age: [30, 44, 64, 65+]

您如何只需要 10 个具有真/假值的组合:21-30, 21-44, 21-64, 21-65+, 30-44, 30-64, 30-65+, 45-65, 45-65+, 65+-65+

职业

这是另一个难点。由于我们已经提交了info.languages,因此我们不能将其作为包含数组的查询。我们确实有一些选择要考虑。

  1. 每个职业类型发出 1 个查询,并合并结果 客户端。这是更多的代码,但直截了当。
  2. 根本不查询该字段,而是过滤掉客户端不匹配的任何文档。假设错误匹配的数量很少,否则您将阅读大量最终丢弃的文档。
  3. 一种混合方法,您可以将职业(例如 [白色、蓝色、粉红色] 领子)和针对其他领域讨论的相同方法进行分类,然后在客户端按特定职业进行过滤。

最终查询

按照上面的操作,你最终会得到类似的东西:

preferences = `preferences.lookingForCheck.${prefCombo}`;
ageRange = `ageRange.${lowerRange}to${upperRange}`;

var usersMatchesCollection = config.db.collection("Users");
var currentUserMatchesAllData = usersMatchesCollection.where(preferences, '==', docDataPreferences.lookingForMatch)
.where('info.identifyAs', '==', docDataPreferences.prefIdentifyAs)
.where('info.languages', 'array-contains-any', docDataPreferences.prefLanguages) 
.where(ageRange, '==', docDataPreferences.ageRange) 
.where('profession', '==', docDataPreferences.prefProfessionCollarCheck) 
.where('education', '==', docDataPreferences.prefEducation) 
.where('kids', '==', docDataPreferences.prefKids) 
.where('married', '==', docDataPreferences.prefMarried) 
.where('drinking', '==', docDataPreferences.prefDrinking) 
.where('smokingCig', '==', docDataPreferences.prefSmokingCig) 
await currentUserMatchesAllData.get().then( function (matchesQuerySnapshot) {
  matchesQuerySnapshot.forEach(function(doc) {
      // Filter by profession here
      console.log('doc data: ' + JSON.stringify(doc.data().id));
  })
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2018-11-22
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多