【问题标题】:Firebase database query by substring in specific ids通过特定 ID 中的子字符串查询 Firebase 数据库
【发布时间】:2019-12-18 14:43:30
【问题描述】:

我的数据库结构如下:

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”,用户ID: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)
                    }
                }
            }
        }
    }

【问题讨论】:

  • 不能在firestore中检查子串,因为这是firestore的限制,但是你可以集成algolia来检查子串firebase.google.com/docs/firestore/solutions/search
  • 感谢您的回答,所以如果我使用完整字符串,而不是子字符串。仅查询特定用户帖子的最佳方法是什么?循环?还是 firebase 提供了比我上面所做的更有效的其他方法? @ked
  • 在这种情况下,您将不得不稍微修改您的数据库结构,我将在一段时间内编写下面的解决方案,并且我将在 kotlin 中编写 firestore 查询,我希望那会是足以理解逻辑
  • 检查下面的解决方案,我猜你使用的是firestore,但如果你使用的是实时数据库,你不能在实时数据库上进行查询
  • @ked 我可能误解了您的评论,但您当然可以查询实时数据库。见Sorting and filtering data。如果您需要更深层次的查询,可以通过深度查询来完成。见Ordering by deep paths

标签: swift firebase firebase-realtime-database


【解决方案1】:

正如上面 cmets 中所讨论的,您必须按如下方式修改数据库结构

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 并单击链接以生成复合索引,创建索引后它将起作用

【讨论】:

    【解决方案2】:

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

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

    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"
    

    然后查询将是

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

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

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

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

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

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

    这可能不适用于您的用例,但它是一个非常酷的选择,可以满足未来的发展需求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多