Oli*_*via 3 firebase react-native google-cloud-firestore
就像问题所述,Firebase 只允许每个查询一个 array-contains-any ( 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));
})
})
Run Code Online (Sandbox Code Playgroud)
您要求的是 Cloud Firestore 无法提供的查询,因为我们无法以无论数据如何都可扩展的通用方式来执行此操作。您可以使用一些技巧来降低查询复杂性,这意味着减少需要分解的查询数量。
对于该where('preferences.lookingFor', 'array-contains-any', docDataPreferences.lookingFor)条件,假设可能的不同值是有限的并且总数已知,您可以创建可能性的映射并将其简化为单个等式。例如,
让我们假设 3 个可能的值A、B、 和C,并且您必须至少有 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>,
}
Run Code Online (Sandbox Code Playgroud)
这些在写入时计算起来相当简单,并且意味着您可以轻松计算要查询的字段: where('preferences.lookingForCheck.BC', '==', true)
这个可能是为了扩展想要组合爆炸,所以就保留这个吧。
我会过度简化,并假设一些简单的桶,所以:21-30, 31-44, 45-64, 65+。您可以像上面那样创建显式字段(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,所以我们不能将其作为包含数组的查询。我们确实有一些选择需要考虑。
按照上面的步骤,你最终会得到类似的结果:
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));
})
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1589 次 |
| 最近记录: |