我有一个聊天应用,我需要将用户联系人与用户集合匹配。
// assume there is 100 contacts
const phoneContacts = {"91302034403": "Salman", "xxx": "xxx"};
// assume there is 30 contacts
const contactsUsingMyApp = ["91302034403", "xxx"];
// assume there is 30000 users
const snap = await db.collection('users').get();
const docs = snap.docs;
for (let i = docs.length - 1; i >= 0; i--) {
const data = docs[i].data();
const phone = data.phone;
if (phoneContacts[phone] !== undefined){
contactsUsingMyApp.push(phone);
}
}
出了什么问题?
现在让我们计算一下
200 x 30000 = 6000000 read operations
每天 $0.06/100000 reads
6000000/100000 = 60 * $0.06 * 30day = $108/m
以上内容也可伸缩,并且仅针对读取操作计算,这确实很昂贵,如何减少它,直到可以使用firebase?
为什么我要阅读整个收藏集以进行注册?因为注册中只有一个请求。
为什么我不像下面那样寻找用户联系人,因为与上面的操作相比,操作要少得多,因为有许多请求
// assume there is 100 contacts
const phoneContacts = {"91302034403": "Salman", "xxx": "xxx"};
const phonesArray = Object.keys(phoneContacts);
for (let i = phonesArray.length - 1; i >= 0; i--) {
const snap = await db.collection('users')
.where("phone", "==", phonesArray[i]).get();
if (snap.size > 0){
// this contact is registered with this app
}
}
不,您看到的是,有很多请求,就像我们在循环中所请求的一样。
答案 0 :(得分:1)
in
query可能允许您以较少的每位用户读取次数来实现此目的,但是由于in查询最多需要10个值,因此您需要按块检查联系人:
const chunk = (arr, size) => arr.length ? [arr.slice(0, size), ...chunk(arr.slice(size), size)] : [];
const contactsWithApp = Promise.all(
chunk(Object.keys(phoneContacts)).map(
it => db.collection("users").where("phone", "in", it).get()
)
).flat();
或者,您可以在应用程序中缓存所有用户,并不时更新缓存:
let phones = new Set();
async function updateCache() {
phones = new Set();
(await db.collection("users").get()).forEach(user => phones.add(user.phone));
}
const contactsWithApp = Object.keys(phoneContacts).filter(it => phones.has(it));