【发布时间】:2020-11-06 15:29:30
【问题描述】:
首先感谢您阅读本文并提供任何建议和帮助的任何人。非常感谢。
我正在为我父亲的企业(专业承包商)开发一个小型定制 CRM(哎哟),我正在为我的数据库使用 Firestore。它应该非常精简,没有太多“金光闪闪”,但与他的专业承包业务密切相关,这很难让任何其他定制 CRM 应用到他的流程中。我已经取得了相当大的进展,并且实现了相当大的规模,但是随着一切都在扩展,我现在遇到了一些非常基本的问题。
我承认,在正确设置我的数据库结构时,我只有在关系数据库方面的经验(而且也没有太多经验)让我摸不着头脑,并且在使用 Firestore 时遇到了一些问题。我也是一个相当新手的开发人员,我觉得我正在处理一些超出我能力范围的东西。 (但现在这个旅程已经一年了,并没有太多转机)
到目前为止,我正在使用顶级集合来展示我在这里展示的内容。我最近开始将子集合用于其他一些次要功能,并开始质疑是否应该将其应用于所有内容。 我预见到的一个大问题是因为我想以多种方式查询,此时我已经消耗了近 100 个复合索引。还有很多东西要添加,所以我需要减少我当前和未来数据结构所需的复合索引的数量。
所以我有点确定,我的数据模型可能存在严重缺陷,需要改进/优化/更改。 (如果需要的话,我不介意这样做,但我对“如何”感到迷茫)我不需要特定的解决方案,但一般来说,可能只是一些关于可用方法的指针。我想我可能缺少一个“啊哈”的时刻。如果我理解一种模式,我通常可以将其进一步应用到其他领域。
我将把我的“销售线索集合”作为这篇文章的核心关注点,因为它有最多的查询变化。
所以我有一个像这样的主要顶级集合结构,但也想添加前缀,除了将 ID 写入其他文档之外,我将“存储”整个“客户”或“销售代表”对象/文档与其他文档和我有云函数,当有更新等时将遍历某些文档(为了避免额外的读取,即当我阅读 SalesLead 时,我不需要阅读 SalesRep 和客户文档,因为它们也被隐藏了/与 SalesLead 嵌套)
| /sales_reps //SalesReps Collection
| /docId //Document ID
| + salesRepId (document id)
| + firstName
| + lastName
| + other employee/salesRep related info etc.
| /customers //Customers Collection
| /docId //Document ID
| + customerId (document id)
| + firstName
| + lastName
| + address + other customer specific related info such as contact info (phone, email) etc.
从逻辑上讲,销售线索当然与客户相关联(一对多,一个客户可以有多个线索)。 下面提到的所有字段我都需要能够“查询”和“过滤”
| /sales_leads //SalesLeads Collection
| /docId //Document ID
| + customerId (document id) <- this is what I would query by to look for leads for a specific customer
| + salesRepId (document id) <- this is what I would query by to look for leads for a specific sales Rep
| + status <- (String: "Open", "Sold", "Lost", "On Hold)
| + progress <- (String: "Started", "Appointment scheduled", "Estimates created", etc. etc., )
| + type <- (String: New Construction or Service/Repair)
| + jobTye <- (String: Different Types job Jobs related to what type of structures they are; 8-10 types right now)
| + reference <- (String: How the lead was referred to the company, i.e. Facebook, Google, etc. etc. );
| + many other (non queryable) data related to a lead, but not relevant here...
SalesEstimates 以一对多的关系与潜在客户相关。 (一个领导可以有很多估计)但是估计与这个讨论并不完全相关,但无论如何只想包括它。不过,我以与潜在客户非常相似的方式查询和过滤估计值。 (类似领域等)
| /sales_estimates //SalesEstimates Collection
| /docId //Document ID
| + salesLeadId (document id) <- this is what I would query by to look for estimates for a specific lead
| + customerId (document id) <- this is what I would query by to look for estimates for a specific customer
| + salesRepId (document id) <- this is what I would query by to look for estimates for a specific sales Rep
| + specific sales Lead related data etc....
在客户端的“销售线索列表”中,我有一些下拉框作为过滤器,其中包含值(即销售代表),但也有一个选项/值“全部”来否定任何过滤。
所以我会开始组装一个查询:
Query query = db.collection("sales_leads");
//Rep
if (!salesRepFilter.equals("All")) { //Typically only Managers/Supervisors woujld be able to see "all leads" whereas for a SalesRep this would be set on his own ID by default.
query = query = query.whereEqualTo("salesRepId", salesRepId);
}
//Lead Status (Open, Sold, Lost, On Hold)
if (!statusFilter.contains("All")) {
query = query.whereEqualTo("status", statusFilter);
}
//Lead Progress
if (!progressFilter.contains("All")) {
query = query.whereEqualTo("progress", progressFilter);
}
//Lead Type
if (!typeFilter.contains("All")) {
query = query.whereEqualTo("leadType", typeFilter);
}
//Job Type
if (!jobTypeFilter.contains("All")) {
query = query.whereArrayContains("jobTypes", jobTypeFilter);
}
//Reference
if (!referenceFilter.contains("All")) {
query = query.whereEqualTo("reference", referenceFilter);
}
此外,我可能希望将整个查询减少到单个客户(这通常意味着跳过所有其他过滤器并“显示 this 客户的所有潜在客户)。如果用户打开客户页面/详细信息,然后单击“显示此客户的潜在客户”之类的内容。
//Filter by Customer (when entering my SalesLead List from a Customer Card/Page where user clicked on "Show Leads for this Customer")
if (filterByCustomer) {
query = query.whereEqualTo("customerId", customerFilter);
}
//And at last I want to be able to query the date Range (when the lead was created) and also sort by "oldest" or "newest"
//Date Range
query = query.whereGreaterThan("leadCreatedOnDate", filterFromDate);
.whereLessThan("leadCreatedOnDate", filterToDate;
//Sort Newest vs Oldest
if (sortByNewest) { //either newest or oldest
query = query.orderBy("leadCreatedOnDate", Query.Direction.ASCENDING);
} else {
query = query.orderBy("leadCreatedOnDate", Query.Direction.DESCENDING);
}
这将完成我对销售线索的查询。这一切都很好现在,但我很担心继续前进并最终达到复合索引的限制。我没有确切的数字,但我可能会为我的 sales_leads 集合提供 25-30 个综合索引。 (哎呀!)
不仅有许多字段可供查询,所需的复合索引的数量还要乘以可能的过滤器集的组合。 (呃)
我需要能够查询所有潜在客户,然后按上述字段过滤它们(在描述我的 sales_leads 集合时)。
因此,与其将所有这些集合保留为顶级集合,我猜测我应该以某种方式通过娱乐子集合来重组我的数据库,但我尝试用不同的方法对此进行建模,但似乎总是碰壁。
我想我可以将“sales_leads”作为每个客户对象下的子集合,并且可以使用集合组查询来检索“所有潜在客户”,但是那些需要复合索引,对吗?所以这只是一个可搜索字段的权衡。 (..撞墙..)
抱歉,篇幅较长。我希望它是可读的。我感谢任何帮助、反馈和意见。我处于一个非常焦虑和沮丧的境地。
如果这不起作用,我可能需要考虑专业咨询。
谢谢!
【问题讨论】:
标签: firebase google-cloud-firestore