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

Swift 通过特定ID中的子字符串查询Firebase数据库,swift,firebase,firebase-realtime-database,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: t

我的数据库结构如下所示:

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)
                    }
                }
            }
        }
    }

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

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中显示错误,即生成检查logcat并单击链接以生成复合索引,在创建索引后,它将工作

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

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

输出是

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)

这可能不适用于您的用例,但它是一个非常酷的选项,并允许未来的增长。

您不能在firestore中检查子字符串,因为这是firestore的限制,但您可以集成algolia来检查子字符串,感谢您的回答,因此如果我使用完整字符串,而不是子字符串。仅查询特定用户的帖子的最佳方式是什么?循环?或者firebase提供了比我上面所做的更有效的方法@kedin如果是这样的话,你必须稍微修改一下你的数据库结构,我会在一段时间内编写下面的解决方案,我会用kotlin编写firestore查询,我希望这足以理解逻辑检查下面的解决方案,我猜你正在使用firestore,但如果您使用的是实时数据库,则无法对实时数据库进行查询database@ked我可能误解了你的评论,但你当然可以查询实时数据库。看见如果您需要查询更深的级别,则可以通过深度查询完成。看见
let query = postsRef.queryOrdered(byChild: "pod/uid1_milk").queryEqual(toValue: true)