我正在尝试对Firestore集合执行按模式筛选。例如,在我的Firestore数据库中,我有一个名为adidas
的品牌。用户将有一个搜索输入,输入“ADI”、“ADID”、“Adida”或“Adidas”将返回adidas
文档。我指出了几个解决方案来做到这一点:
1.获取所有文档并执行前端筛选
var brands = db.collection("brands");
filteredBrands = brands.filter((br) => br.name.includes("pattern"));
由于Firestore的定价,这个解决方案显然不是一个选项。此外,如果文档数量很高,执行请求可能会相当长。
2.使用Elasticsearch或Algolia
这可能很有趣。然而,我认为添加这些解决方案只支持模式搜索有点矫枉过正,而且这会很快变得昂贵。
3.创建对象时自定义searchname
字段
所以我有这样的解决方案:在创建文档时,创建一个包含可能搜索模式数组的字段:
{
...
"name":"adidas",
"searchNames":[
"adi",
"adida",
"adidas"
],
...
}
以便可以通过以下方式访问该文件:
filteredBrands = db.collection("brands").where("searchNames", "array-contains", "pattern");
所以我有几个问题:
IMHO,第一个解决方案肯定不是一个选项。下载一个完整的集合来在客户端搜索字段是不实际的,而且成本很高。
考虑到将帮助您在整个Cloud Firestore数据库中启用全文搜索的事实,第二个选项是最佳选项。由你来决定是否值得使用它。
您认为第三种解决方案的针对性和效率如何?
关于第三种解决方案,它可能有效,但这意味着即使品牌名称很长,也要创建一个可能的搜索模式数组。正如我在您的模式中看到的,您正在添加从第3个字母开始的可能的搜索模式,这意味着如果有人正在搜索ad
,将不会找到任何结果。这个解决方案的缺点是,如果您有一个名为ASICSTiger
的品牌,而用户正在搜索TIG
或TIGE
,那么您最终将再次没有结果。
对于在Firestore集合上执行模式筛选,您有什么其他想法吗?
如果您有兴趣只从一个单词中得到结果,并使用品牌的醒目字母作为模式,我推荐您一个更好的解决方案,它使用如下所示的查询:
var brands = db.collection("brands");
brands.orderBy("name").startAt(searchName).endAt(searchName + "\uf8ff")
在这种情况下,类似a
或AD
的搜索将非常好地工作。除此之外,将不需要创建任何其他数组。这样就会减少文档写入。