有一个Firestore集合,用于存储配方和一系列配料。我们需要找到至少包含一种成分的食谱。如何执行呢?使用Firestore可以做到这一点吗?
--- recipe1
|
--- ingredients: ["salt", "pepper", "sucar"]
--- recipe2
|
--- ingredients: ["pepper"]
--- recipe3
|
--- ingredients: ["salt", "pepper"]
如何选择其中包含“ 胡椒” 或“ 盐”的食谱?
答案 0 :(得分:0)
这可以在Firestore吗?
是的。
我们需要找到包含至少一种成分的食谱。如何实现?
为了实现此功能,您应该使用数组。请在下面查看数据库架构,它可以帮助您实现这一目标:
Firestore-root
|
--- recipes (collection)
|
--- recipeId (document)
|
--- ingredients: ["salt", "pepper"] (array)
|
--- //other decipe details
要查找包含一种成分的所有食谱,您应该使用如下查询:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = rootRef.collection("recipes").whereArrayContains("ingredients", "salt");
这是针对Android的,但您可以通过相同的方式针对其他编程语言来实现。请参阅here更多详细信息。
但是请注意,在不对数据库进行重大更改的情况下,您不可能找到所有包含一种以上成分的食谱。 Firestore 不允许不允许链接的whereArrayContains()
调用。因此,您可以获得所有仅包含一种成分成分的食谱。
编辑:根据您的评论:
如何选择有“胡椒粉”或“盐”的配方?
您需要知道Firestore中没有OR
子句。根据我在 post 中的回答,您应该创建两个单独的查询并合并结果客户端。
编辑2:
100,000个可在客户端上组合的食谱。
如果这是您应用程序的用例,那么您应该以这种方式进行查询。 Firestore可大规模扩展。
但这是一个相当简单的查询!
就SQL数据库而言,这就是NoSQL数据库的工作方式。
如果您需要排除包含“糖”成分的食谱?
根据官方文档,除了没有OR
子句的事实之外,还有另一个query limitation:
带有!=子句的查询。在这种情况下,您应该将查询分为大于查询和小于查询。
因此,这是解决exclude
或not equal
情况的方法。
您的链接也不能解决问题。
我的链接无法解决无法以您想要的方式解决的问题,它仅表示Firestore官方文档提供的约束。在该链接中,我还按照文档推荐的方式提供了一种解决方法。在这种情况下,您应该根据我的答案和该帖子中的信息进行尝试,并询问是否还有其他问题。
结果-盐和胡椒粉食谱。但是不能加盐或胡椒粉!
否,如果您创建两个单独的查询并合并结果提示端,那么您将获得所需的结果。我已经对其进行了测试,并且效果很好。
我知道不存在“或”。因此,我问-有解决方案吗?
是的,我上面提供的解决方案是最简单的。如果您对此不满意,则还可以考虑更改整个数据库结构,以便可以根据反向查询进行组织。您的结构应如下所示:
Firestore-root
|
--- salt_peper (collection)
| |
| --- recipeId (document)
| | |
| | --- //recipe with salt
| |
| --- recipeId (document)
| |
| --- //recipe with peper
|
--- salt_sugar (collection)
|
--- recipeId (document)
|
--- //recipe details
如您所见,这是数据库的另一个架构。第一个集合将为您提供所有食盐OR
胡椒粉的食谱。
这种做法称为denormalization
,是Firebase的常见做法。为了更好地理解,我建议您观看此视频Denormalization is normal with the Firebase Database。它用于Firebase实时数据库,但相同的原理也适用于Cloud Firestore。
此外,在复制数据时,需要记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。
我还建议您从此 post 看一下我的回答,以了解有关上述技术的利弊。