通过特定ID中的子字符串查询Firebase数据库

时间:2019-12-18 14:43:30

标签: swift firebase firebase-realtime-database

我的数据库结构如下:

posts:
   pid1:
      timestamp: 111
      pod:
         title: "eggs"
   pid2:
      timestamp: 222
      pod:
         title: "milk"
   pid3:
      timestamp: 333
      pod:
         title: "bread"


users_posts:
   uid1:
      pid1: true
      pid2: true

我想获取uid1包含特定子字符串的所有title帖子。

例如:

输入: 子字符串:“ gs”,userId:uid1

输出:pid1

最好的方法是什么?

这是我到目前为止所做的:

func queryPosts(withSearchText searchText: String, userId: String, completion: @escaping (Post) -> Void) {
        REF_USER_POSTS.child(userId).observeSingleEvent(of: .value) { (snapshot) in
            let ids = (snapshot.value as! [String: Any]).keys
            for id in ids {
                REF_POSTS.child(id).observeSingleEvent(of: .value) { (snapshot) in
                    if let dict = snapshot.value as? [String: Any],
                        let title = ((dict["pod"] as? [String: Any])?["title"] as? String)?,
                        title.contains(searchText) {
                        print("found result", id)
                    }
                }
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

如上面评论中所讨论的,您必须按如下所示修改数据库结构

posts:
   pid1:
      timestamp: 111
      createdBy: "uid1"
      title: "eggs"
   pid2:
      timestamp: 222
      createdBy: "uid1"
      title: "milk"
   pid3:
      timestamp: 333
      createdBy: "uid2"
      title: "bread"


users_posts:
   uid1:
      pid1: true
      pid2: true

用于按特定用户获取所有帖子并匹配字符串,请使用以下查询

FirebaseFirestore.getInstance().collection("posts")
            .whereEqualTo("createdBy","uid1")
            .whereEqualTo("title","eggs")
            .get()
            .addOnCompleteListener {
                //all posts written by user and matching the title eggs
            }
            .addOnFailureListener { 
                it.printStackTrace()
            }

在最初运行此查询时,它将在logcat中显示错误,提示generate composite index检查logcat并单击链接以生成复合索引,在创建索引后它将起作用

答案 1 :(得分:0)

您可以使用深度查询轻松查询子节点。

例如,假设您要查询title =“ milk”的所有节点

dock container run --name nginx --volume /hosthome/mazoo/DockerExampleFolder/html:/usr/share/nginx/html -p 80:80 nginx:latest

输出为

func performDeepQuery() {
    let postsRef = self.ref.child("more_posts")
    let query = postsRef.queryOrdered(byChild: "pod/title").queryEqual(toValue: "milk")
    query.observeSingleEvent(of: .value, with: { snapshot in
        let allChildren = snapshot.children.allObjects as! [DataSnapshot]
        for snap in allChildren {
            let postId = snap.key
            let timestamp = snap.childSnapshot(forPath: "timestamp").value as? String ?? "No Timestamp"
            print(postId, timestamp)
        }
    })
}

话虽如此,这不会查询特定用户的帖子。这将查询所有帖子。但是,您可以通过添加另一个节点以使节点特定于用户来轻松解决该问题

pid2 222

,查询将为

   pid2:
      timestamp: 222
      pod:
         title: "milk"
         uid_title: "uid1_milk"

这是一个复合值,在NoSQL数据库中很常见。

如果要扩展该范围,请翻转该值,以便可以将多个用户链接到单个帖子

let query = postsRef.queryOrdered(byChild: "pod/title").queryEqual(toValue: "uid1_milk")

然后您可以查询任何有牛奶的用户。

   pid2:
      timestamp: 222
      pod:
         title: "milk"
         uid1_milk: true
         uid2_milk: true

这可能不适用于您的用例,但这是一个非常不错的选择,并且可以用于将来的发展。