【问题标题】:How to query firebase to filter on a certain value如何查询firebase以过滤某个值
【发布时间】:2018-01-18 23:51:06
【问题描述】:

我正在尝试获取针对特定用户 (UserId) 的所有活动的所有 imageURL。快照的内容包括正确的条目,但是 imageURL 未附加到 imageArray。我做错了什么?

 // Get all images for a specific user

    func getImagesForUser(userId:String, handler: @escaping (_ imageArray: [String]) -> ()) {
        var imageArray = [String]()

        REF_ACTIVITY.queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with:  { snapshot in
            dump(snapshot)
            guard let data = snapshot.value as? NSDictionary else { print("else was returned"); return }

            let imageURL = data["imageURL"] as? String ?? ""
            imageArray.append(imageURL)
            handler(imageArray)
        })

    }

转储输出(快照)

Snap (-L2RDXTKANzD8YGpPl92) {
    gearId = asfasfsf;
    imageCount = 3;
    imageURLs =     {
        1 = "http://www.foo.com";
        2 = "http://www.foo2.com";
        3 = "http://www.foo3.com";
    };
    killCount = 10;
    kills = 12;
    likeCount = 2;
    likes =     {
        fas86q39rasf = 1;
    };
    userId = NhZZGwJQCGe2OGaNTwGvpPuQKNA2;
}

Snap (-L2RDXTKANzD8YGpPl92) {
    gearId = asfasfsf;
    imageCount = 3;
    imageURLs =     {
        1 = "http://www.foo.com";
        2 = "http://www.foo2.com";
        3 = "http://www.foo3.com";
    };
    killCount = 10;
    kills = 12;
    likeCount = 2;
    likes =     {
        fas86q39rasf = 1;
    };
    userId = NhZZGwJQCGe2OGaNTwGvpPuQKNA2;
}

更新 - Dict 的输出

24 elements
  ▿ 0 : 2 elements
    - key : "commentCount"
    - value : 1
// removed some info
...
  ▿ 12 : 2 elements
    - key : "imageURLs"
    ▿ value : 4 elements
      - 0 : <null>
      - 1 : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
      - 2 : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
      - 3 : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
  ▿ 13 : 2 elements
    - key : "imageURL"
    - value : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
  ▿ 14 : 2 elements
    - key : "killCount"
    - value : 10

【问题讨论】:

标签: swift firebase firebase-realtime-database


【解决方案1】:

问题中的代码有几个问题:

您似乎只想获取一次数据,但 observe 将保持连接状态,并且只要该节点中与查询匹配的任何位置发生更改,您就会收到通知。如果您只想要一次,请改用 observeSingleEvent

此外,您将使用该查询返回多个节点 - 这些节点需要通过循环一次处理一个以迭代返回的数据。

这是该技术的一个非常简化的示例。注意没有错误检查;例如,如果返回的节点之一不包含应该使用保护或零合并运算符 (??) 处理的 imageURL 键,以在这种情况下分配默认值。

let activitesRef = self.ref.child("activities")
let query = activitesRef.queryOrdered(byChild: "userId").queryEqual(toValue: userId)
query.observeSingleEvent(of: .value, with: { snapshot in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        let dict = snap.value as! [String: Any]
        let url = dict["imageURL"] as? String ?? "no url"
        print(url)
    }
})

编辑:

这段代码采用这样的结构

activities
  activity_0
     userId: "uid_0"
     imageURL: "www.someurl.com"
  activity_1
     userId: "uid_1"
     imageURL: "www.anotherurl.com"
  activity_2
     userId: "uid_0"
     imageURL: "www.coolurl.com"

在上述情况下,快照中将返回两个节点,上面的代码将遍历这些节点并打印每个节点的 url。

www.someurl.com
www.coolurl.com

另一个编辑:

根据一些后续的 cmets,似乎每个用户都有多个 url。这是要匹配的更新后的 Firebase 结构:

activities
  activity_0
     userId: "uid_1"
     urls
       url_0: "www.someurl.com"
       url_1: "www.anotherurl.com"
       url_2: "www.coolurl.com"
  activity_1
     userId: "uid_1"
     urls
       url_0: "www.thisurl.com"
       url_1: "www.thaturl.com"
       url_2: "www.ou812url.com"

请注意,在 NoSQL 数据库中应避免使用数组,因此我们使用 url_0、url_1 但实际上这些节点键应使用 childByAutoId 创建。

然后是查询所有节点的 uid_1 并打印其 url 的代码

let activitesRef = self.ref.child("activities")
let query = activitesRef.queryOrdered(byChild: "userId").queryEqual(toValue: userId)
query.observeSingleEvent(of: .value, with: { snapshot in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        print(snap.key)
        let urlSnap = snap.childSnapshot(forPath: "urls")
        for url in urlSnap.children {
            let aUrlSnap = url as! DataSnapshot
            let key = aUrlSnap.key
            let val = aUrlSnap.value as! String
            print("  key: \(key)  url: \(val)")
        }
    }
})

最后是输出

activity_0
  key: url_0  url: www.someurl.com
  key: url_1  url: www.anotherurl.com
  key: url_2  url: www.coolurl.com
activity_1
  key: url_0  url: www.thisurl.com
  key: url_1  url: www.thaturl.com
  key: url_2  url: www.ou812url.com

【讨论】:

  • 感谢您的意见。我已经玩了一段时间了,但没有成功。它在 let dict 行上失败了...... Swift 还表明这将永远失败......我还没有设法修复它......
  • @Chris_1983_Norway 哎呀!我在代码中有错字;需要 snap.value 而不是 snap。 Snap 是一个快照,而 snap.value 是我们需要的数据。立即尝试-对此非常抱歉。我应该在发布之前对其进行测试。它现在已经过测试,将迭代并打印 userId 等于您正在寻找的 uid 的所有 url。我还添加了一个 nil 合并运算符来保护代码,以防其中一个快照中没有 imageURL 节点。
  • 不用担心。是我感谢您抽出时间提供帮助。
  • @Chris_1983_Norway 我希望答案有帮助!如果是这样,请务必接受它,这样它也可以帮助其他人。
  • 我仍在为此苦苦挣扎。我还将 imageURLs 更改为多个图像的字典。请参阅更新的问题以打印出“dict”。我想我需要循环通过它来将它添加到本地数组?
猜你喜欢
  • 2018-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 2018-05-08
  • 1970-01-01
相关资源
最近更新 更多