FireStore - 如何绕过数组“不包含"查询

FireStore - how to get around array quot;does-not-containquot; queries(FireStore - 如何绕过数组“不包含查询)
本文介绍了FireStore - 如何绕过数组“不包含"查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过一些研究,很明显我不能使用 FireStore 来查询给定数组不包含的项目.有人对此用例有解决方法吗?...

After some research, it's seems clear that I cannot use FireStore to query items a given array does NOT contain. Does anyone have a workaround for this use case?...

用户注册后,应用会获取一堆卡片,每张卡片在 FireStore 中都有对应的卡片"文档.用户与卡片交互后,卡片文档将用户的 uid 添加到字段数组(例如:usersWhoHaveSeenThisCard:[userUID]),用户"文档将卡片的 uid 添加到字段数组(例如:cardThisUserHasSeen:[cardUID]).用户"文档存在于用户"集合中,卡片"文档存在于卡片"集合中.

After a user signs up, the app fetches a bunch of cards that each have a corresponding "card" document in FireStore. After a user interacts with a card, the card document adds the user's uid to a field array (ex: usersWhoHaveSeenThisCard: [userUID]) and the "user" document adds the card's uid to a field array (ex: cardsThisUserHasSeen: [cardUID]). The "user" documents live in a "user" collection and the "card" documents live in a "card" collection.

目前,我想获取用户未与之交互的所有卡片.但是,这是有问题的,因为我只知道用户与之交互的卡片,因此 .whereField(usersWhoHaveSeenThisCard, arrayContains: currentUserUID) 将不起作用,因为我需要一个不存在的arrayDoesNotContain"语句.

Currently, I'd like to fetch all cards that a user has NOT interacted with. However, this is problematic, as I only know the cards that a user has interacted with, so a .whereField(usersWhoHaveSeenThisCard, arrayContains: currentUserUID) will not work, as I'd need an "arrayDoesNotContain" statement, which does not exist.

最后,用户不能拥有卡片,因此我无法在卡片文档中创建真/假布尔字段(例如:userHasSeenThisCard: false)并根据该条件进行搜索.

Finally, a user cannot own a card, so I cannot create a true / false boolian field in the card document (ex: userHasSeenThisCard: false) and search on that criteria.

我能想到的唯一解决方案是在卡片文档上创建一个新的字段数组,其中包括所有没有看到卡片的用户(例如:usersWhoHaveNotSeenThisCard: [userUID]),但这意味着每个用户注册必须将他们的 uid 写入 1000 多个卡片文档,这会占用我的数据.

The only solution I can think of, would be to create a new field array on the card document that includes every user who has NOT seen a card (ex: usersWhoHaveNotSeenThisCard: [userUID]), but that means that every user who signs up would have to write their uid to 1000+ card documents, which would eat up my data.

我可能只是运气不好,但我希望对 NOSQL/FireStore 更了解的人可以提供一些见解.

I might just be out of luck, but am hoping someone more knowledgeable with NOSQL / FireStore could provide some insight.

// If any code sample would help, please let me know and I'll update - I think this is largely conceptual as of now

推荐答案

有一个公认的很好的答案,但是,它不能直接解决这个问题,所以这里......(这可能会也可能不会有帮助,但确实有效)

There is an accepted and good answer, however, it doesn't provide a direct solution to the question so here goes... (this may or may not be helpful but it does work)

我不确切知道您的 Firestore 结构是什么,所以这是我的假设:

I don't know exactly what your Firestore structure is so here's my assumption:

cards
   card_id_0
      usersWhoHaveSeenThisCard
         0: uid_0
         1: uid_1
         2: uid_2
   card_id_1
      usersWhoHaveSeenThisCard
         0: uid_2
         1: uid_3
   card_id_2
      usersWhoHaveSeenThisCard
         0: uid_1
         1: uid_3

假设我们想知道 uid_2 没有看到哪些卡 - 在本例中是 card_id_2

Suppose we want to know which cards uid_2 has not seen - which in this case is card_id_2

func findCardsUserHasNotSeen(uidToCheck: String, completion: @escaping ( ([String]) -> Void ) ) {
    let ref = self.db.collection("cards")

    ref.getDocuments(completion: { snapshot, err in
        if let err = err {
            print(err.localizedDescription)
            return
        }

        guard let docs = snapshot?.documents else {
            print("no docs")
            return
        }
        var documentsIdsThatDoNotContainThisUser = [String]()
        for doc in docs {
            let uidArray = doc.get("usersWhoHaveSeenThisCard") as! [String]
            let x = uidArray.contains(uidToCheck)
            if x == false {
                documentsIdsThatDoNotContainThisUser.append(doc.documentID)
            }
        }
        completion(documentsIdsThatDoNotContainThisUser)
    })
}

那么,这样的用例

func checkUserAction() {
    let uid = "uid_2" //the user id to check
    self.findCardsUserHasNotSeen(uidToCheck: uid, completion: { result in
        if result.count == 0 {
            print("user: (uid) has seen all cards")
            return
        }
        for docId in result {
            print("user: (uid) has not seen: (docId)")
        }
    })
}

和输出

user: uid_2 has not seen: card_id_2

此代码遍历文档,获取存储在每个文档 usersWhoHaveSeenThisCard 节点中的 uid 数组,并确定 uid 是否在数组中.如果没有,它会将 documentID 添加到 documentsIdsThatDoNotContainThisUser 数组中.检查完所有文档后,将返回不包含用户 ID 的文档 ID 数组.

This code goes through the documents, gets the array of uid's stored within each documents usersWhoHaveSeenThisCard node and determines if the uid is in the array. If not, it adds that documentID to the documentsIdsThatDoNotContainThisUser array. Once all docs have been checked, the array of documentID's that do not contain the user id is returned.

知道 Firestore 的速度有多快,我针对一个大型数据集运行了代码,结果很快就返回了,因此对于大多数用例来说它不会造成任何延迟.

Knowing how fast Firestore is, I ran the code against a large dataset and the results were returned very quickly so it should not cause any kind of lag for most use cases.

这篇关于FireStore - 如何绕过数组“不包含"查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Why local notification is not firing for UNCalendarNotificationTrigger(为什么没有为UNCalendarNotificationTrigger触发本地通知)
Pushing UIViewController above UITabBar(将UIView控制器推送到UITabBar上方)
Dropbox Files.download does not start when number of files in folder is gt; 1000(当文件夹中的文件数为1000时,Dropbox Files.Download不会启动)
appearance().setBackgroundImage Not Working On Custom Class(外观().setBackoundImage在自定义类上不起作用)
Show/Hide barButtonItem(显示/隐藏barButtonItem)
Using Firebase Firestore in offline only mode(在仅脱机模式下使用Firebase FiRestore)