优化检索由Firebase的Firestore中的另一个Collection分组的数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优化检索由Firebase的Firestore中的另一个Collection分组的数据相关的知识,希望对你有一定的参考价值。

我的Firestore数据库中有两个集合,相当于:

// ItemCategories collection
{
    id_category_1: {
        name: 'Category 1',
    },
    id_category_2: {
        name: 'Category 2',
    },
    id_category_3: {
        name: 'Category 3',
    },
    // ...
}

// Items collection
{
    id_item_1: {
        CategoryId: 'id_category_1',
        name: 'Item 1',
    },
    id_item_2: {
        CategoryId: 'id_category_1',
        name: 'Item 2',
    },
    id_item_3: {
        CategoryId: 'id_category_3',
        name: 'Item 3',
    },
    id_item_4: {
        CategoryId: 'id_category_2',
        name: 'Item 4',
    },
    // ...
}

我想检索和格式化我的项目按类别分隔,如下:

const ItemList = {
    'Category 1': [
        {
            id: 'id_item_1',
            CategoryId: 'id_category_1',
            name: 'Item 1',
        },
        {
            id: 'id_item_2',
            CategoryId: 'id_category_1',
            name: 'Item 2',
        },
    ],
    'Category 2': [
        {
            id: 'id_item_4',
            CategoryId: 'id_category_2',
            name: 'Item 4',
        },
    ],
    'Category 3': [
        {
            id: 'id_item_3',
            CategoryId: 'id_category_3',
            name: 'Item 3',
        },
    ],
};

我目前正在处理一堆Promises:

// Function to retrieve Items for a given CategoryId
const getItemsByCategory = async CategoryId => {
    const Items = await new Promise(resolve => {
        firebase
            .firestore()
            .collection('items')
            .where('CategoryId', '==', CategoryId)
            .orderBy('name', 'ASC')
            .onSnapshot(querySnapshot => {
                const values = [];
                querySnapshot.forEach(doc => {
                    values.push({
                        ...doc.data(),
                        key: doc.id,
                    });
                });
                resolve(values);
            });
    });
    return Items;
};

// Function to actually get all the items, formatted as wanted
export const getItemList = () => {
    return dispatch => { // I'm in a Redux Action
        const Items = {};

        firebase
            .firestore()
            .collection('itemCategories')
            .orderBy('name', 'ASC')
            .get() // Categories can't be changed
            .then(querySnapshot => {
                const Promises = [];
                querySnapshot.forEach(doc => {
                    const category = doc.data().name;

                    const P = new Promise(resolve => {
                        getItemsByCategory(doc.id).then(values => {
                            const result = {
                                category,
                                values,
                            };
                            resolve(result);
                        });
                    });

                    Promises.push(P);
                });

                Promise.all(Promises).then(values => {
                    values.forEach(v => {
                        Items[v.category] = v.values;
                    });

                    // Here I have the formatted items
                    console.log(Items); 
                    //dispatch(setItemList(Items)); // Redux stuff
                });
            });
    }
};

这段代码正在运行,但我觉得应该有办法优化它。我至少可以看到两个问题:

  • 此代码进行(N + 1)个Firestore调用(其中N是类别的数量)。随着Firebase对每次通话收费,我无法看到这种扩展。
  • 我们必须等待N个承诺实际显示数据;如果类别数量增长太多,执行时间可能会成为一个问题。

有没有比我更好的解决方案?

答案

随着Firebase对每次通话收费,我无法看到这种扩展。

Firestore不会根据“电话”收费。它对读取的文档数量和传输的数据量收费。如果您需要阅读所有类别,那么您只需支付阅读该集合的大量文档。读取这些文档需要多少次调用无关紧要(例外情况是返回0结果的查询仍会导致一次读取)。

在实践中,在等待返回N个文档的1个查询或每个返回1个文档的N个查询之间没有太大的区别。您仍然只是在等待N个文档。使用Firestore时,没有任何查询无法很好地扩展。限制因素始终取决于收到的文件数量,而不是查询数量。您的代码主要花费时间等待结果传输。当然,你可以在记忆中拥有的东西有一个实际的上限,但承诺的数量并不是一件大事。

除此之外,我不明白为什么你在onSnapshot使用getItemsByCategory。好像你只想使用get()而不是只在侦听器中接收一个结果。你的代码会更加简单。

以上是关于优化检索由Firebase的Firestore中的另一个Collection分组的数据的主要内容,如果未能解决你的问题,请参考以下文章

检索数据时出现 Vue/Firestore/Firebase 错误

Android Studio Firebase Firestore 无法检索字段数据

如何从Swift中的Cloud FireStore Firebase访问特定字段

Firestore 如何存储对文档的引用/如何检索它?

我可以通过哪些方法正确地在 Firebase Firestore 中的数据结构来建模多对多关系以检索 vue js 中的特定 uid

firestore firebase storage 以较低的分辨率检索图像