使用 Algolia 搜索时,如何为具有变体的项目构建 firestore collection?

How to structure a firestore collection for items with variants, when using Algolia Search?

所以正如标题所暗示的那样,我在 firestore 中有一个项目 collection,看起来像这样:

ParentCollection
    items
        ->docId_1
            ->name: 'Shirt'
            ->price: 5
            ->tags: ['tag1', 'tag2', 'tag3']
            ->attribute1: 'blah'
            ->attribute2: 'blahblah'

但是,我需要这些项目有变体,例如不同的 sizes/color/etc。在这种结构中,唯一的方法是为每个变体提供一个全新的项目。这不理想,

这是我目前对要求的看法:

我目前的计划是这样的:

ParentCollection

    items
        ->parentDocId_1
            ->name: 'Shirt'
            ->variants : [{
                size: S,
                available: true,
                variantDocId: variantDocId_1
                },{
                size: L,
                available: false,
                variantDocId: variantDocId_2
                }]
            ->tags: ['tag1', 'tag2', 'tag3']
            ->attribute1: 'blah'
            ->attribute2: 'blahblah'

                SubCollection
                    variants
                        ->variantDocId_1
                            ->size: 'S'
                            ->price: 5
                            ->parentDocId: parentDocId_1
                        ->variantDocId_2
                            ->size: 'L'
                            ->price: 10
                            ->parentDocId: parentDocId_1

我可以看出一些问题。

  1. 这将需要额外的数据库调用,因为 Firestore 在请求 parent collection 时无法获取子 Collection。

  2. 一个大问题是我需要为项目附加一个可用属性,以前我在项目 collection 级别有它,但现在我有变体我需要把它放在每个变体上。如果我在 parent collection 级别的变体数组中有它,我认为我不能再在 algolia 搜索中过滤可用,因为一个项目将有多个值。如果我在变体 sub collection 中放入 available down,则它不会被 algolia 索引,因为它仅索引项目 collection 中的文档。不确定这里的解决方案是什么。

我真的不想有子 collection,我想我可以在没有子 collection 的情况下执行上述操作,只需将所有唯一属性合并到变体数组中。但是我不会为每个变体都有一个唯一的 docId,而且我很确定我需要它(还不完全确定)。它也没有解决我的可用属性问题。

关于如何正确执行此操作的任何想法?有没有办法不用 sub collection?

事实证明,此问题的解决方案更多地与 algolia 搜索有关,而不是与 firestore 有关。为了实现我想要的,我可以让我的 firestore 数据库非常接近它原来的样子(不需要子集合),我只需要添加一个对象数组,其中包含每个变体的唯一信息(variants: [] ) 以及将各个文档绑定在一起作为彼此变体的标识符 (distinct: 12345)。

这里的关键是 aloglia 的 distinct 功能,它允许删除由特定键绑定在一起的项目的重复项。因此,在下面的示例中,我通过 distinct: 12345 字段将 Shirt 项目的三个变体联系在一起。您必须进入 aloglia 仪表板以打开 distinct 并设置键名。现在只有一个变体会在搜索时显示(这取决于自定义排名或过滤器),但我可以通过变体字段访问所有变体的信息。这允许我为每个变体拥有唯一的 ID,并且每个变体的所有属性都可以在 algolia 搜索中过滤。它还允许我构建一个选择下拉列表来选择用户想要与之交互的变体。一个警告是添加了冗余,并且在更新项目变体时,它将需要一个云函数来将更改传播到所有变体。但它有效并且问题已解决!

ParentCollection
    items
        ->docId_1
            ->name: 'Shirt,
            ->tags: ['tag1', 'tag2', 'tag3']
            ->attribute1: 'blah'
            ->attribute2: 'blahblah'
            ->distinct: 12345
            ->variants: [
                {
                 size: 'S',
                 available: true,
                 price: 5, 
                 docId: docId_1
                },
                {
                 size: 'M',
                 available: false,
                 price: 10,
                 docId: docId_2
                },
                {
                 size: 'L',
                 available: true,
                 price: 15, 
                 docId: docId_3
                }]
        ->docId_2
            ->name: 'Shirt'
            ->tags: ['tag1', 'tag2', 'tag3']
            ->attribute1: 'blah'
            ->attribute2: 'blahblah'
            ->distinct: 12345
            ->variants: [
                {
                 size: 'S',
                 available: true,
                 price: 5, 
                 docId: docId_1
                },
                {
                 size: 'M',
                 available: false,
                 price: 10,
                 docId: docId_2
                },
                {
                 size: 'L',
                 available: true,
                 price: 15, 
                 docId: docId_3
                }]
        ->docId_3
            ->name: 'Shirt'
            ->tags: ['tag1', 'tag2', 'tag3']
            ->attribute1: 'blah'
            ->attribute2: 'blahblah'
            ->distinct: 12345
            ->variants: [
                {
                 size: 'S',
                 available: true,
                 price: 5, 
                 docId: docId_1
                },
                {
                 size: 'M',
                 available: false,
                 price: 10,
                 docId: docId_2
                },
                {
                 size: 'L',
                 available: true,
                 price: 15, 
                 docId: docId_3
                }]