FireStore-如何避开数组“不包含"询问 [英] FireStore - how to get around array "does-not-contain" queries

查看:30
本文介绍了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添加到字段数组(例如:cardsThisUserHasSeen:[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.

最后,用户无法拥有卡,因此我无法在卡文档中创建true/false布尔值字段(例如: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的documentID数组.

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-如何避开数组“不包含"询问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆