【问题标题】:Android - Database Structure (Firebase)Android - 数据库结构 (Firebase)
【发布时间】:2017-10-31 12:13:30
【问题描述】:

我有一个应用程序,其中包含三种用户类型:“学校”、“年长学生”和“年幼的孩子”。学校在地图上制定不同的路线,并指派年龄较大的学生负责该路线。学校还在路线上设置了多个停靠点。停靠站是年长学生接年幼孩子的地方。

在我的应用程序中,学校用户类型能够在地图上设置两个标记,并且将在两个标记之间绘制一条路径(路线)。我想保存两个标记的 LatLng,因为它们指示路线的开始和结束。我还想保存两个标记的地址。我使用地理编码器来获取路线的地址。

学校也可以一次只添加一个标记(停止)。当放置标记时,提示用户输入标记的地址以及年龄较大的学生应该接回年龄较小的孩子的时间。我想保存 LatLng、标记的地址和输入的时间。

学校应该能够看到在列表视图中创建的路线,其中显示了开始地址、结束地址、停止地址和时间。单击列表视图中的路线时,应显示所有年长学生的列表,学校可以将年长学生指定为路线负责人。

年长的学生可以看到他们被分配到的路线和站点。

年幼的孩子应该只能看到停靠点。通过点击地图上的标记,他们表示他们想在那个站点上车。

到目前为止,我的 firebase 数据库的结构是:

School Name
   users
     userID
       username 
       usertype
   markers
     uniqueID
       latitude
       longitude
       address
       time
   routes
     uniqueID
        startAddress
        endAddress
        locations
           0
             latitude
             longitude
           1
             latitude
             longitude

其中位置节点是路线的航路点数组。这种结构很难满足我的要求。有更好的数据库结构的想法吗?

public class Route {

private ArrayList<MapFragment.Location> locations;

private String startDestination;
private String endDestination;
HashMap<String, Boolean> markerId;


public Route() {
}

public Route(ArrayList<MapFragment.Location> locations, String startDestination, String endDestination, HashMap<String, Boolean> markerId) {
    this.locations = locations;
    this.startDestination = startDestination;
    this.endDestination = endDestination;
    this.markerId = markerId;
}

public String getStartDestination() {
    return startDestination;
}

public void setStartDestination(String startDestination) {
    this.startDestination = startDestination;
}

public String getEndDestination() {
    return endDestination;
}

public void setEndDestination(String endDestination) {
    this.endDestination = endDestination;
}


public ArrayList<MapFragment.Location> getLocations() {
    return locations;
}

public void setLocations(ArrayList<MapFragment.Location> locations) {
    this.locations = locations;
}


}

【问题讨论】:

  • 您能否详细说明当前的结构(主要是非规范化的)如何难以满足您的要求?
  • 由于路线和标记位于具有不同唯一ID 的不同节点中,因此无法知道哪些标记(站点)连接到哪些路线。因此,如果一个年长的学生被分配到一条路线,那个年长的学生不知道具体路线上有哪些标记。
  • 想法:将标记节点放在路由节点内不是更好的解决方案吗?所以应该是routes/uniqueID/markers
  • 你有什么想法吗?还是我应该坚持我原来的结构
  • 我认为您需要开始使用 ID 作为索引来扇出您的数据,如 create data that scales documentation 中所述。我很快就会写一个答案。

标签: android firebase firebase-realtime-database


【解决方案1】:

听起来这些对象之间的关系可以概括为:

我们知道,Firebase 实时数据库是一个 NoSQL 数据库,因此不明确支持关系,但可以在结构中推断它们,因此以这个结构为例(其中 ... 是您现有的值):

schoolId
  users
    userId
      ...
  markers
    markerId
      ...
      route      // the route ID that this marker belongs to
  routes
    routeId
      ...
      markers    // list of marker IDs that belong to this route

注意:为了简单起见,我暂时忽略users 关系,只处理markersroutes 之间的关系。

使用这种结构:无论我们当前使用的是标记还是路线,我们都可以轻松找出它们之间的关系。

然后很容易通过performing a query 对照标记节点中子节点的route 值获取与特定路线相关的所有标记:

schoolReference.child("markers").orderByChild("route").equalTo(routeId);

routeId 是我们当前正在使用的路线的唯一 ID。

但是,您在创建对象时需要注意一些变化,例如,当您使用这种结构创建标记时,您需要:

  • 将标记的route值设置为其所属路由的ID,并
  • 将标记ID添加到其所属路由下的markers列表中。

您可以使用transactionmulti-location update 在一次写入操作中实现此目的。

注意:您实际上不必使用routeId/markers 列表,但如果您使用FirebaseUI to display indexed data,它会很有用。

这种使用 ID 作为索引键的技术称为数据扇出,您可以在 structure your database documentation 中了解更多信息。

【讨论】:

  • 感谢您的回答。关于routeId和markerId,是不是来自push()方法?
  • 没错,您可以使用push()为每个新对象生成一个唯一ID。
  • 到目前为止,我可以在地图上制作多个标记,但是当我单击“保存路线和标记”按钮时,它只需要我在地图上放置的最后一个标记并保存它。有没有办法用单独的 makerId 插入所有标记?
  • 您需要使用push() 为要存储在数据库中的每个新对象创建一个新的唯一ID。这作为一个单独的问题可能会更好,因为我们可能需要查看该按钮的代码。
  • 是的,我同意。我得到了第一部分的工作。所以我现在只在一个标记的标记节点中插入 routeId。新线程:stackoverflow.com/questions/47039831/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
相关资源
最近更新 更多