这是我的第一个Firestore和NoSQL项目,我正努力为数据建模。
我有许多物体(大约在500到1000之间)可以在全球范围内旅行。他们会定期(大约每天一次)签入,以发送地理位置信息和一些其他数据。
换句话说,有一千个缓慢积累的跟踪数据流。
如何最好地构造数据以优化以下查询? 对于每个目标对象,给我最后的N个跟踪位置,从最新到最旧的排序。我假设N在100到300左右。
编辑:为明确起见,这将返回大约1000 x(100到300)的跟踪位置。可以在没有1000个查询的情况下完成此操作(即每个对象一个)?
答案 0 :(得分:1)
以下数据库结构应适合您的用例。
Firestore-root
|
--- drivers (collection)
| |
| --- driverId (document)
| |
| --- //other driver details
|
--- data (collection)
| |
| --- driverId (document)
| |
| --- driverData (collection)
| |
| --- driverDataId (document) //Same object as below
| |
| --- geoPoint: [[48.858376° N, 2.294537° E]]
| |
| --- date: Oct 11, 2018 at 6:16:58 PM UTC+3
| |
| --- driverId: "DriverUserId"
| |
| --- //other extra data
|
--- allData (collection)
|
--- driverDataId (document) //Same object as above
|
--- geoPoint: [[48.858376° N, 2.294537° E]]
|
--- date: Oct 11, 2018 at 6:16:58 PM UTC+3
|
--- driverId: "DriverUserId"
|
--- //other extra data
他们定期(大约每天一次)签入以发送地理位置信息和一些其他数据。
假设您有一个驱动程序每天发送一次数据的模型类,应将其发送到数据库的对象应在两个不同的位置发送:>
data (collection) -> driverId (document) -> driverData (collection) -> driverDataId (document)
和
allData (collection) -> driverDataId (document)
对于所有对象,请给我最后N个跟踪位置,从最新到最旧排序。
要获取所有这些对象,需要这样的查询:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference allDataRef = rootRef.collection("allData");
Query query = allDataRef.orderBy("date", Query.Direction.ASCENDING).limit(n);
如果还要获取驱动程序详细信息,则需要进行额外的get()
调用,以便获取其详细信息。您可以使用driverId
作为驱动程序数据对象中的属性存在。
如果要从单个驱动程序获取所有这些对象,则应使用以下查询:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference allDataRef = rootRef.collection("data").document(driverId).collecton("driverData");
Query query = allDataRef.orderBy("date", Query.Direction.ASCENDING).limit(n);
这种做法称为denormalization
,是Firebase的常见做法。为了更好的理解,我建议您观看此视频Denormalization is normal with the Firebase Database。它用于Firebase实时数据库,但相同的原理也适用于Cloud Firestore。
此外,在复制数据时,需要记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。
编辑:
根据您的评论,我现在了解您的意思。在这种情况下,您可以考虑allData
收集一个提要,您应该在其中添加驱动程序数据对象。假设n = 100
。这意味着每次在第100个对象之后添加新对象时,都需要删除最旧的对象。因此,这意味着额外的删除操作。这样,您将只在该供稿中保留特定用户的100个对象。是的,如果您有1000个用户,并且每个用户有100个数据对象,则需要查询包含10万个文档的集合。因此,如果您希望一次拥有所有这些数据,那么将执行10万次读取。
编辑2:
我可以考虑另一个模式,但这意味着要进行一些测试,因为我不知道您的驱动程序数据对象有多大。因此,请在下面查看我的架构:
Firestore-root
|
--- drivers (collection)
|
--- driverId (document)
|
--- //other driver details
|
--- driverData (map)
|
--- driverDataId (document) //Same object as below
|
--- geoPoint: [[48.858376° N, 2.294537° E]]
|
--- date: Oct 11, 2018 at 6:16:58 PM UTC+3
|
--- driverId: "DriverUserId"
|
--- //other extra data
如您所见,我在驱动程序对象中将driverData
集合更改为map
。在这种情况下,您还应该在该地图中维护那100个对象。在这种情况下,只需要1000个查询,就可以返回10万个驱动程序数据对象。但是要注意,问题是文件有限制。因此,在文档中可以放入多少数据方面存在一些限制。根据有关usage and limits的官方文档:
文档的最大大小:1 MiB(1,048,576字节)
如您所见,单个文档中的数据总数限制为1 MiB。当我们谈论存储文本时,可以存储很多,但是随着对象图越来越大,请注意此限制。