【问题标题】:Firebase & swift use .indexOn to sort data snapshotFirebase 和 swift 使用 .index 对数据快照进行排序
【发布时间】:2016-07-08 12:17:14
【问题描述】:

我是 Firebase/swift 新手,我正在尝试使用 .indexOn 对服务器上的一组节点进行排序。我已经搜索了 SO 和文档以编写规则,但我在为 swift 代码使用索引的正确格式而苦苦挣扎。

我的假设是,当我使用 .indexOn 规则时,返回的快照使用该索引对结果进行排序。通过在 swift 中使用 .queryOrderedByChild("title") 我否定了创建索引的服务器端性能优势。如果这个假设不正确,请纠正我。

这是我的 Firebase 数据库结构的简化 sn-p:

{
  "users": {
    "GkdjgdBJh1TxuAzIPezLWRouG9f2": {
      "messages": {
        "-KM0crettRl-RLQQdmMQ": {
          "body": "Anyone want a bit of body string?",
          "title": "5 Another title string",
        },
        "-KM0dhkChY6ZQ2QzuPlC": {
          "body": "This is a short body string",
          "title": "1 A lovely title string",
        },
        "-FQ0dhkChY6ZQ2Qzu3RQv": {
          "body": "Short and sweet body string",
          "title": "3 I should be in the middle",
        }
      }
    }
  }
}

这是我的 JSON 规则:

{
    "rules": {
        ".read": true,
        ".write": true,
        "users": {
              "$userid": {
                    "messages": {
                          ".indexOn": ["title"]
                    }
              }
        }
    }
}

这是我的快速代码:

if let user = FIRAuth.auth()?.currentUser {
    // user is logged in

    // *** I think this is the line with the issue ***
    FIRDatabase.database().reference().child("users").child(user.uid).child("messages").observeEventType(.Value, withBlock: { (snapshot) in
    messageArray = []

        if let dictionaryOfMessages = snapshot.value as? [String: AnyObject] {
            for messageKey in dictionaryOfMessages.keys {
                messageArray.append(Message(json: JSON(dictionaryOfMessages[messageKey]!)))
                // set the messageId
                messageArray[messageArray.count - 1].messageId = messageKey
            }
        }
        // return the data to the VC that called the function
        success(messages: messageArray)
    }) { (error) in
        // Handle the Error
    }
} else {
    // return some generic messages about logging in etc.
}

任何关于我如何修改我的 Swift 代码以使用索引(或纠正索引如果错误)的建议都会很棒。

【问题讨论】:

  • 我对你的问题并不完全清楚。添加索引后,您是否看到负面的性能影响?还是您的结果显示不正常?
  • 嗨@FrankvanPuffelen - 请记住我是新手,所以我有点困惑。我的结果目前按它们存储在 Firebase 中的顺序显示,而不是按索引排序。我在文档中读到,最好使用 .indexOn 在服务器上进行排序,因此决定预先进行(我的数据集可能会变得非常大),因此我无法在此阶段评论性能。
  • 好的,知道了。我会写一个答案。对于未来的问题,最好只提及出错的部分。如果数组中的元素与您期望的顺序不同,则使用索引对性能的影响是无关紧要的
  • @FrankvanPuffelen - 谢谢。我明白你的意思。但是,由于我是一个困惑的新手,我不确定我的 indexOn 是否错误,或者即使 indexOn 正确到位,我仍然应该使用 .queryOrderedByChild() 以某种方式查看预期排序顺序的结果。我想我的问题可能是:“在规则 JSON 中有一个 .indexOn 是否消除了在检索排序数据时使用 .queryOrderedByChild() 的需要?”
  • 最后一个确实是一个非常明确的问题。答案是不”。下面回答。 Jad 是第一个,但你可能也需要我的。

标签: swift firebase firebase-realtime-database


【解决方案1】:

首先,您需要按照 Jad 的回答并指定接收子节点的顺序。一个列表可以有多个索引,您需要指定此特定查询的顺序。

指定顺序后,Firebase 数据库会返回一个快照,其中包含与您的查询匹配的节点以及有关这些节点在结果中出现的顺序的信息。

但是字典没有关于孩子顺序的任何信息。因此,当您的代码将快照转换为字典时,有关订单的所有信息都会丢失:

if let dictionaryOfMessages = snapshot.value as? [String: AnyObject] {

因此,最好使用快照的内置方法来迭代子节点:

for child in snapshot.children {
  let key = child.key as String
  print(key)
  messageArray.append(Message(json: JSON(child.value)))  // JSON handling via SwiftyJSON
  // set the messageId
  messageArray[messageArray.count - 1].messageId = key
}

【讨论】:

  • 感谢您确认 Jad 的回答以及有关词典的提示。如果客户端必须在结果到达后对其进行排序,我仍然不确定添加索引的客户端性能优势来自哪里,但我会继续前进:-)
  • 客户端不订购它们,它只是以正确的顺序返回它们。字典是无序的,因此通过转换为字典,您将所有的排序都扔掉了。
  • @FrankvanPuffelen 基于 OP 的代码,如果我尝试使用 Swift 库(不使用 REST API)读取数据库,我还需要修改 Firebase 实时数据库中的规则吗?酷儿的表现会提高吗?
【解决方案2】:

您需要在请求数据时使用 queryOrderedByChild 并在您的规则中设置一个键。这是一个例子;

Firebase 文档

以下示例演示了如何检索按星数排序的用户热门帖子列表:

// My top posts by number of stars
let myTopPostsQuery = (ref.child("user-posts").child(getUid())).queryOrderedByChild("starCount")

此查询根据用户 ID 从数据库中的路径检索用户的帖子,按每个帖子获得的星数排序。这种使用 ID 作为索引键的技术称为数据扇出。

对 queryOrderedByChild 方法的调用指定了对结果进行排序的子键。在这种情况下,帖子按每个帖子中“starCount”子项的值排序。有关其他数据类型如何排序的详细信息,请参阅查询数据的排序方式。

请点击链接了解更多详情;

https://firebase.google.com/docs/database/ios/retrieve-data

【讨论】:

  • 谢谢 - 我认为我的困惑源于我在文档中读到的事实,即向规则添加索引是个好主意。因此,我假设索引而不是使用.queryOrderedByChild()。正如@FrankVanPuffelen 已确认您的答案是正确的,我会听从您的建议并继续前进。非常感谢
猜你喜欢
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
  • 2017-01-30
  • 1970-01-01
  • 2016-05-27
相关资源
最近更新 更多