当数组包含日期时,从 Firestore 中删除数组项不起作用

2023-12-13

我花了几天时间研究这个问题,包括各种答案,例如:Firebase Firestore:从文档数组中追加/删除项目以及我之前的问题:从 Firestore 中删除数组项但无法弄清楚如何真正使其发挥作用。事实证明,问题在于对象中存在日期属性,如下所示:

我有两个结构:

struct TestList : Codable {
    var title : String
    var color: String
    var number: Int
    var date: Date
    
    var asDict: [String: Any] {
        return ["title" : self.title,
                "color" : self.color,
                "number" : self.number,
                "date" : self.date]
    }
}

struct TestGroup: Codable {
    var items: [TestList]
}

我可以使用添加数据FieldValue.arrayUnion:

  @objc func addAdditionalArray() {
        let testList = TestList(title: "Testing", color: "blue", number: Int.random(in: 1..<999), date: Date())
        let docRef = FirestoreReferenceManager.simTest.document("def")
        docRef.updateData([
            "items" : FieldValue.arrayUnion([["title":testList.title,
                                             "color":testList.color,
                                             "number":testList.number,
                                             "date": testList.date]])
        ])
    }

上述工作原理如 Firestore 仪表板所示:

enter image description here

但如果我尝试删除数组中的一项,它就不起作用。

  @objc func deleteArray() {
        let docRef = FirestoreReferenceManager.simTest.document("def")
        docRef.getDocument { (document, error) in
            do {
                let retrievedTestGroup = try document?.data(as: TestGroup.self)
                let retrievedTestItem = retrievedTestGroup?.items[1]
                guard let itemToRemove = retrievedTestItem else { return }
                docRef.updateData([
                    "items" : FieldValue.arrayRemove([itemToRemove.asDict])
                ]) { error in
                    if let error = error {
                    print("error: \(error)")
                } else {
                    print("successfully deleted")
                }
                }

            } catch {

            }
        }
    }

我已经打印了itemToRemove到日志来检查它是否正确。但它只是不会将其从 Firestore 中删除。没有返回错误,但是"successfully deleted"已记录。

我尝试了不同的变体,只要结构/对象中没有日期属性,此代码就可以工作。当我添加日期字段时,它就会中断并停止工作。关于我在这里做错了什么有什么想法吗?

请注意:我已尝试传递上述字段值FieldValue.arrayUnion以及对象FieldValue.arrayRemove无论我使用哪种方法,同样的问题仍然存在。


正如您所指出的,问题是Date场地。这是一个问题,因为 Firestore 不保留原生Date对象存储在数据库中时 - 它们会转换为 Firestore 原生的日期对象。这两种数据类型之间的桥梁是令牌系统。例如,当您从 Swift 客户端将日期写入 Firestore 时,您实际上向数据库发送了一个令牌,然后服务器在令牌到达时对其进行兑换,然后在数据库中创建 Firestore 日期对象。相反,当您在 Swift 客户端上从 Firestore 读取日期时,您实际上会收到一个令牌,然后客户端会兑换该令牌,然后您可以将其转换为 SwiftDate目的。因此,“现在”的定义在客户端和服务器上并不相同,存在差异。

也就是说,为了从 Firestore 数组中删除特定项目,您必须重新创建该确切项目以提供给FieldValue.arrayRemove(),正如您现在可以想象的那样,这对于日期来说是很棘手的。与 Swift 不同,您无法通过索引从 Firestore 数组中删除项目。因此,如果您想保持数据架构不变(因为我将在下面解释一个解决方法),最安全的方法是从服务器获取项目本身并将其传递到FieldValue.arrayRemove()。您可以通过常规读取来执行此操作,然后在完成处理程序中执行删除,或者您可以在事务中以原子方式(更安全)执行它。

let db = Firestore.firestore()

db.runTransaction { (trans, errorPointer) -> Any? in
    let doc: DocumentSnapshot
    let docRef = db.document("test/def")
    
    // get the document
    do {
        try doc = trans.getDocument(docRef)
    } catch let error as NSError {
        errorPointer?.pointee = error
        return nil
    }
    
    // get the items from the document
    if let items = doc.get("items") as? [[String: Any]] {
        
        // find the element to delete
        if let toDelete = items.first(where: { (element) -> Bool in
            
            // the predicate for finding the element
            if let number = element["number"] as? Int,
               number == 385 {
                return true
            } else {
                return false
            }
        }) {
            // element found, remove it
            docRef.updateData([
                "items": FieldValue.arrayRemove([toDelete])
            ])
        }
    } else {
        // array itself not found
        print("items not found")
    }
    return nil // you can return things out of transactions but not needed here so return nil
} completion: { (_, error) in
    if let error = error {
        print(error)
    } else {
        print("transaction done")
    }
}

我之前提到的解决方法是完全绕过令牌系统。最简单的方法是使用 Unix 时间戳将时间表示为整数。这样,日期就以整数形式存储在数据库中,这几乎就是您期望的存储方式。这使得查找包含日期的数组元素变得更加简单,因为客户端上的时间现在等于服务器上的时间。令牌的情况并非如此,因为存储在数据库中的实际日期是兑换令牌的时间,而不是创建令牌的时间。

你可以延长Date方便地将日期转换为时间戳并扩展Int方便地将时间戳转换为日期:

typealias UnixTimestamp = Int

extension Date {
    var unixTimestamp: UnixTimestamp {
        return UnixTimestamp(self.timeIntervalSince1970 * 1_000) // millisecond precision
    }
}

extension UnixTimestamp {
    var dateObject: Date {
        return Date(timeIntervalSince1970: TimeInterval(self / 1_000)) // must take a millisecond-precision unix timestamp
    }
}

最后一件事是,在我的示例中,我通过其数字字段(我使用了您的数据)找到了要删除的元素,我认为它是唯一标识符。我不知道这些元素的性质以及它们如何唯一标识,因此将我的代码中的过滤谓词视为纯粹的假设。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当数组包含日期时,从 Firestore 中删除数组项不起作用 的相关文章

  • iOS 上每个选项的带有图像的操作表

    有没有办法在 iOS 上将图像添加到操作表中 与苹果在应用程序商店或苹果音乐应用程序上所做的一样 我对苹果文档的基本搜索表明我没有在操作表中子类化或添加子视图 UIActionSheet 并非设计为子类化 也不应向其层次结构添加视图 苹果文
  • Swift 数组设置索引值不起作用

    我有一个方法 下面的内容 其中queue2只是一个 Int 我打印了很多东西 看看一切是否都正常 public func cool item Int println item println back queue2 insert item
  • 如何在 Swift 中使用 CGFloat?

    var posinonY Float Float y Float pipeDown size height Float verticalPipeGap pipeDown position CGPointMake 0 0 Float posi
  • 新的 FUITableViewDataSource - 如何使用?雨燕3

    刚刚更新到较新的 FirebaseUI Pod 有些事情发生了变化 但其中最大的变化之一是 FUI 表视图的工作方式 我让它在旧版本上运行良好 但在下面遇到了困难 并且缺乏文档 示例 self dataSource FUITableView
  • Firebase 连接管理器应仅返回一个结果

    我正在关注位于以下位置的文档 https www firebase com docs ios guide offline capability html section connection state https www firebase
  • iOS 内存警告

    我正在尝试使用从 Parse 数据库下载的图像填充集合视图 但我收到内存警告 然后偶尔崩溃 有谁知道其他应用程序如何设法呈现这么多图像而不崩溃 有人可以告诉我如何优化我已有的东西吗 这是所有相关代码 https gist github co
  • Swift -boundingBox 导致 EXC_BAD_ACCESS (代码 = 1)

    我正在使用 SceneKit 来显示文本节点 这是我的代码 foo swift extension SCNNode func getNodeSize gt width Float height Float let min max bound
  • 路径中包含空格的 Firestore 安全规则

    我需要为名为 测试用例 的子集合创建一个 firestore 规则 由于 firestore 规则不是用 javascript 编写的 因此我似乎无法在匹配后获取路径来接受空格而不会出现错误 我尝试过引号 转义字符的反斜杠 以及将整个路径放
  • 使用 Azure AD B2C 进行 Firebase 身份验证

    我有一个用 xCode Swift 开发的本机 iOS 应用程序 它集成了Firebase 身份验证 https firebase google com docs auth 用于新用户注册和登录的SDK Firebase Auth 系统应链
  • 如何自动为 Swift 类创建初始化程序?

    UPDATE 使用结构而不是类 struct 在很多方面都更好 它有自己的初始化器 这是我的模型课 是否有可能创建init自动方法 每次我都必须将所有变量一一初始化 这会花费很多时间 class Profile var id String
  • 是否可以将 Cypress e2e 测试与 firebase auth 项目结合使用?

    我正在探索 Cypress 进行 e2e 测试 看起来是很棒的软件 问题在于身份验证 Cypress 文档解释了为什么使用 UI 非常糟糕here https docs cypress io guides getting started t
  • UICollectionView 列的垂直偏移

    右图是我试图实现的目标 Does anyone know how I could achieve this on a two column UICollectionView I m able to discern my columns by
  • 在 iOS 上的 SceneKit 中导入 3d 模型

    从 URL 导入 obj 文件并将其转换为 SCNNode 时遇到问题 这是代码 swift3 let url URL init string https cloud box com shared static ock9d81kakj91d
  • Firebase 函数,在用户不活动 15 分钟后运行

    我创建了一个 firebase 存在系统 如图所示在 Firebase 中建立影响力 https firebase google com docs firestore solutions presence文档 现在 我尝试在用户离线 15
  • Xcode UI 测试 - 通过 id 在 Webview 中查找元素

    我们的应用程序是混合的 包含 webview 我正在尝试使用 Xcode UI 测试自动化我们的应用程序 我能够使用以下方法找到网络按钮 let app XCUIApplication app launch let button app s
  • Firebase Messaging FCM 在可配置的时间间隔内分发

    当您使用 FCM 向给定应用程序的所有设备发送推送时 这可能会导致许多用户同时打开他们的应用程序 从而导致大量服务器轮询 从而导致负载峰值 有没有一种方便的方法可以在给定的时间间隔内分发消息以进行计划推送 最后 我们找到了一种可能的方法 通
  • Swift 中不再有“private init”?

    我看到很多关于使用的参考private init在 Swift 中限制对象构造 例如this http krakendev io blog the right way to write a singleton 但当我尝试时 在 Xcode
  • 当 Firebase 函数以 Swift 结束时

    我在我的应用程序中使用 Firebase 它查询大量用户并获取所需的特定数据 但是当它开始查询时 其余功能也继续运行 而不仅仅是查询 所以我无法理解当它结束时 例如在这段代码中 ref observeEventType ChildAdded
  • 在Swift中计算没有透明度的颜色,通过用透明颜色叠加颜色获得

    我有一个具有非透明颜色的原始 UIVieworgColor 这是由一个覆盖 UIView 覆盖的 该 UIView 具有overlayColor具有透明度 alpha 通道 鉴于这两种颜色orgColor and overlayColor我
  • 为什么我们需要将 delegate 设置为 self?为什么编译器不默认它?

    I think我完全理解授权的概念 我的问题是 当我们这样做时 class someViewController UIViewController UITableViewDelegate 会吗ever可能我们不想设置tableView de

随机推荐

  • 如何获取命令行属性来覆盖 Maven 属性

    我有一个 pom 文件 其中某些依赖项的版本号依赖于项目版本pom 文件设置中指定的属性 我可以通过命令行覆盖它吗 如果是这样 怎么办 这是一个很长的故事 我们目前正在将项目转移到 Maven 但还没有完全实现 有多个模块仍然不是使用 ma
  • 使 Silverlight 业务应用程序模板正常工作需要什么数据库?

    我一直在尝试运行 Silverlight 业务应用程序模板 但在尝试注册时失败 我有带有 MSSQLSERVER 实例的 SQL Express 并且定义了创建的标准 aspnetdb 错误是 Submit operation failed
  • 为什么 Console.Readline 没有按预期执行

    我有下面的代码可以使用 我这里遇到的问题是代码在 while 循环中运行 而不等待线路上的输入字符串临时 Console ReadLine 需要帮助了解原因以及如何修复 提前致谢 Banker s algorithm Implementat
  • python - networkx - 使用两个列表绘制不同颜色的节点

    我是 networkx 新手 需要一些帮助 我之前搜索过 但无法解决我的问题 我制作了一个 networkx graphviz 图像 使用列表作为节点的输入 并使用两列文件作为边缘 第二个文件包含第一个列表中的项目以及与节点大小相对应的值
  • 从哪里获取 Alchemyapi API 密钥?

    我正在做的是 Getting Started with AlchemyAPI Using Ruby Ruby 教程 但我似乎找不到我的 API 密钥 Source http www alchemyapi com developers get
  • 我如何在 Laravel 中需要 Composer 自动加载器?

    我要安装guzzlehttps github com guzzle guzzle 我阅读了参考资料 但我对这一部分感到困惑 从该教程中 要求需要 Composer 自动加载器 所以似乎需要添加require vendor autoload
  • C# JSON 中的未包装属性

    我需要反序列化这个 JSON user id 0 resource id 0 resource name file xml 对于这个类 public class Resource public ResourceId ResourceId g
  • Windows 8 / Metro UI 中文本框下的自动完成框

    我想使用 C XAML 在 Windows 8 UI Metro UI 应用程序中的文本框中实现自动完成 目前 当软 触摸键盘显示时 它会遮挡自动完成框 但是 在文本框焦点上 Windows 8 会自动向上滚动整个视图并确保文本框处于焦点位
  • 删除项目后 hasMany 关联列表中为空

    有域对象 class Book List
  • BoxAndWhiskerChart JFreeChart 的绘图方向

    我有一个问题JFreeChart 可以改吗PlotOrientation of a BoxAndWhiskerChart水平 我有一个直方图 我想添加一个BoxAndWhiskerChart以下 我需要它水平 这样我就可以使用相同的轴刻度
  • 如何使用参数化接口?

    我正在努力理解界面 起初 它们看起来很简单 但是一旦我开始使用参数化接口 我就无法让各个部分就位 我有这个界面 interface my if parameter H WIDTH 64 parameter L WIDTH 8 logic H
  • VSTS 嵌套变量

    我正在尝试实现一个级联变量 当设置一个设计时变量时 它会级联到其他变量 这可能吗 我尝试过使用点表示法 尝试过不使用点表示法 并且尝试在任务中执行此操作 我也尝试过这个任务插件 但我的代理使用的是 2 0 并且任务无法运行 变量工具箱任务
  • 从代码隐藏文件中检查 CheckBoxField

    看来 CheckBoxField 不接受 ID 属性 因此我无法直接调用代码隐藏文件中的组件
  • Web 应用程序如何向 iOS 设备发送推送通知? [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我正在开发一个网络应用程序 当有新内容时 如何向 iOS 用户发送推送通知 更具体地说 为了让 Web 应用程序向移动设备 例如 iPhone 发送推送通知 移动设备必须已注册才
  • 使用多处理时 Python 实例变量未更新

    我在更新变量方面遇到了一个不寻常的问题 我构建了一个简单的类对象来帮助我进行一些网络嗅探 我想要创建一个并行进程 它允许我运行一些网络测试并捕获使用 python 生成的流量 这样我就可以扩展程序来完成令人惊奇的事情 我正在使用 scapy
  • 如何使用外部 api 访问令牌而不将其暴露给用户?

    很抱歉 如果这可能是一个微不足道的问题 但我想确定一下 但无法在网上找到明确的答案 我正在编写一个使用 Mapbox 的小应用程序 并且我正在使用反应地图GL为了它 他们需要客户端的访问令牌 因此他们建议使用环境变量 我的问题是 是否可以简
  • 围绕轮廓对象生成颜色直方图

    嘿 OpenCV Emgu 大师们 我有一张正在为其生成轮廓的图像 请参见下文 我正在尝试生成基于颜色直方图的图像搜索空间修剪以查找 如何使蒙版仅围绕突出的物体轮廓并遮挡其余部分 所以我有一个由两部分组成的问题 如何 反转 轮廓外的图像 漫
  • 如何使用 Python 创建一个流式传输在线广播的 Discord 机器人

    正如标题所提到的 我该怎么做呢 到目前为止 我花了几个小时试图找到答案 但由于这不是一个受欢迎的请求 因此没有任何相关内容 我发现的大部分内容只是使用 youtube dl 下载 yt 音频并播放它 编辑 更新以使用FFmpegPCM音频流
  • 从文件中解析逗号分隔的 JSON

    我正在读取一个包含用逗号分隔的 JSON 的文件 例如 JSON JSON JSON 我确定它们是用逗号分隔的 但不确定它们是用换行符分隔的 该 JSON 可能全部位于一行 但可以肯定的是它们是用逗号分隔的 我还没有收到该数据 我想知道如何
  • 当数组包含日期时,从 Firestore 中删除数组项不起作用

    我花了几天时间研究这个问题 包括各种答案 例如 Firebase Firestore 从文档数组中追加 删除项目以及我之前的问题 从 Firestore 中删除数组项但无法弄清楚如何真正使其发挥作用 事实证明 问题在于对象中存在日期属性 如