【问题标题】:Scalability for Firebase Swift: Query vs Duplicate dataFirebase Swift 的可扩展性:查询与重复数据
【发布时间】:2016-05-25 17:08:25
【问题描述】:

我有属于群组的帖子。在可扩展性方面,我正在考虑两种不同的方法:

方法1:通过查询访问的组值发布

结构:

{
 "posts": {
   "1": {
     "message": "hello world",
     "timeAdded": 1718281919,
     "posterId": 123,
     "group": 15
   },
  "2": {
    "message": "this is second"
    "timeAdded": 12717212182,
    "posterId": 124,
    "group": 3
   },
   ...
  }
}

通过如下查询获取一个组,即第 15 组的帖子:

ref.child("posts/group").queryEqualToValue("15").observeEventType(.Value, withBlock: { snapshot in ... })

方法二:组内重复数据

结构:

{
 "posts": {
   "1": {
     "message": "hello world",
     "timeAdded": 1718281919,
     "posterId": 123,
     "group": 15
   },
  "2": {
    "message": "this is second"
    "timeAdded": 12717212182,
    "posterId": 124,
    "group": 3
   },
   ...
  },
  "groups": {
    "15": {
      "posts": {
        "1": {
          "message": "hello world",
          "timeAdded": 1718281919,
          "posterId": 123,
        },
       ...
      }
    },
    ...
  },
  ...
}

获取一个组的,即第 15 组,简单地发帖:

ref.child("groups/15").observeEventType(.Value, withBlock: { snapshot in ... })

哪种设计更适合可扩展性?

编辑:

作为一个附带问题,是否有一个 Firebase 查询可以查询多个值,而不仅仅是一个,即不仅返回第 15 组的帖子,还返回 21、28 等的帖子。

【问题讨论】:

  • 方法一有什么问题?它不做什么?该方法将处理数千个帖子并立即返回属于第 15 组的任何帖子。 (我并不是说它是最好的,只是好奇它有什么问题)
  • @Jay 我需要的关键要求之一,我应该提到的是我必须一次查询几个不同的组。除非有 queryEqualToValue("15,21,24") 类型的查询,否则我认为通过方法 2 在 3 个组 15、21、24 上添加 3 个观察可能会更快。

标签: ios swift firebase scalability firebase-realtime-database


【解决方案1】:

您走在正确的轨道上,但最终会与您所拥有的有所不同。我很确定组织数据的正确方法是将组和帖子作为不同的集合。但是,为了说明帖子属于给定组,只需在该组的“帖子”属性中包含帖子的标识符。

{
 "posts": {
   "1": {
     "message": "hello world",
     "timeAdded": 1718281919,
     "posterId": 123,
     "group": 15
   },
   "2": {
    "message": "this is second"
    "timeAdded": 12717212182,
    "posterId": 124,
    "group": 3
   },
   ...
  },


  "groups": {
    "15": {
      "posts": {
        "1": true,
       }
       ...
      }
    } "3": {
      "posts" : {
         "2":true
       },
    ...
  },
  ...
}

这样,您就可以获取帖子标识符,然后使用它来查询 Firebase 以检索有关该特定帖子的信息。

这个例子有点令人困惑,因为组和帖子的标识符都是低整数值:)

有关更多信息,请参阅 Firebase 的文档:https://firebase.google.com/docs/database/ios/structure-data#flatten_data_structures

希望这会有所帮助!

【讨论】:

  • 感谢您的快速回复。但是,这样每次获取组时,我都必须对每个帖子标识符进行单独的 observeSingleEvent 调用。将整个帖子正文复制到群组帖子中会更节省时间(但更节省空间)吗?
  • 我不能 100% 确定这是否是绝对最快的方法,但由于 Firebase 是使用 Web 套接字实现的,因此时间差可以忽略不计。
【解决方案2】:

由于您经常查询组键,因此应将其设为顶级键:

{
  "posts": {
    "15": {
      "1": {
        "message": "hello world",
        "timeAdded": 1718281919,
        "posterId": 123
      },
      "6": {
        "message": "another post",
        "timeAdded": 1718281919,
        "posterId": 122
      },
    },
    "3": {
      "2": {
        "message": "this is second"
        "timeAdded": 12717212182,
        "posterId": 124
      }
    }
  }
}

这样的结构可以让你获取/posts/15第15组的所有帖子

firebase docs 中的示例与您的数据具有相似的结构,但术语略有不同,“聊天”而不是“群组”和“消息”而不是“帖子”。

【讨论】:

    【解决方案3】:

    方法2中似乎不需要重复数据,所以我建议两种解决方案:

    使用方法1结构

    postsRef.queryOrderedByChild("group").queryEqualToValue("15").observeEventType(.ChildAdded
    postsRef.queryOrderedByChild("group").queryEqualToValue("15").observeEventType(.ChildChanged
    postsRef.queryOrderedByChild("group").queryEqualToValue("15").observeEventType(.ChildRemoved    
    
    postsRef.queryOrderedByChild("group").queryEqualToValue("21").observeEventType(.ChildAdded
    postsRef.queryOrderedByChild("group").queryEqualToValue("21").observeEventType(.ChildChanged
    postsRef.queryOrderedByChild("group").queryEqualToValue("21").observeEventType(.ChildRemoved
    
    postsRef.queryOrderedByChild("group").queryEqualToValue("28").observeEventType(.ChildAdded
    postsRef.queryOrderedByChild("group").queryEqualToValue("28").observeEventType(.ChildChanged
    postsRef.queryOrderedByChild("group").queryEqualToValue("28").observeEventType(.ChildRemoved
    

    这将在 postsRef 上设置观察者,监视第 15、21 和 28 组中的帖子是否有任何新帖子、对现有帖子的更改或已删除的帖子。

    请注意,我建议使用 .ChildAdded、.ChildChanged 和 .ChildRemoved 而不是 .Value,因为 .Value 将返回节点中的所有内容并进行任何更改,这可能是很多数据。

    方法 2 有重复数据,但在这种情况下似乎不需要它,所以只需保留组节点

    "groups": {
        "15": {
          "posts": {
            "1": {
              "message": "hello world",
              "timeAdded": 1718281919,
              "posterId": 123,
    

    并将观察者添加到每个中的帖子节点

    postsRef = groups/15/posts
       ...add observers like above
    postsRef = groups/21/posts
       ...add observers like above
    postsRef = groups/28/posts
       ...add observers like above
    

    我的建议 #2 的缺点是查询,因为结构太深而无法做很多事情 - 但问题中没有指定查询的需要。

    第一个建议提供了简单性、非规范化数据以及查询任何内容的能力。它也快速且有弹性。

    作为旁注,这可能不言而喻,但请不要使用整数 - 连续或其他 - 作为父节点名称。这些应该通过 childByAutoId 获得。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 2017-05-21
      • 2019-07-28
      • 1970-01-01
      • 2016-06-25
      相关资源
      最近更新 更多