Firestore:用于对象跟踪应用程序的数据建模

时间:2018-10-11 09:02:48

标签: firebase nosql google-cloud-firestore data-modeling

这是我的第一个Firestore和NoSQL项目,我正努力为数据建模。

我有许多物体(大约在500到1000之间)可以在全球范围内旅行。他们会定期(大约每天一次)签入,以发送地理位置信息和一些其他数据。

换句话说,有一千个缓慢积累的跟踪数据流。

如何最好地构造数据以优化以下查询? 对于每个目标对象,给我最后的N个跟踪位置,从最新到最旧的排序。我假设N在100到300左右。

编辑:为明确起见,这将返回大约1000 x(100到300)的跟踪位置。可以在没有1000个查询的情况下完成此操作(即每个对象一个)?

1 个答案:

答案 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。当我们谈论存储文本时,可以存储很多,但是随着对象图越来越大,请注意此限制。

相关问题