【问题标题】:How to get a Firestore document size?如何获取 Firestore 文档大小?
【发布时间】:2019-10-13 06:19:21
【问题描述】:

Firestore docs,我们得到Firestore 文档的最大大小 是:

文档的最大大小 1 MiB(1,048,576 字节)

问题

我如何知道单个文档的当前大小,以检查我是否正在接近 那个 1mb 的限制?

示例:

var docRef = db.collection("cities").doc("SF");

docRef.get().then(function(doc) {
    if (doc.exists) {
        console.log("Document data:", doc.data());
        // IS THERE A PROPERTY THAT CAN DISPLAY THE DOCUMENT FILE SIZE?
    } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
    }
}).catch(function(error) {
    console.log("Error getting document:", error);
});

【问题讨论】:

    标签: firebase google-cloud-firestore


    【解决方案1】:

    所以我一直在寻找一种方法,通过在数组中累积数据来减少不必要的文档读取,并担心大小。

    原来我还没有接近极限。

    这是你可以做的, 创建一个新集合并添加一个包含实时数据最坏情况的文档,并使用云控制台导出该集合,您将看到文档大小。

    Here is a screenshot of my export

    假设所有文档大小相等,每个文档大小为 0.0003MB

    还可以查看文档是否超过 1024byte 限制 document exceeding limit 来自控制台

    注意:只有启用结算后才能导出!

    【讨论】:

      【解决方案2】:

      你可以用这个计算器(代码截断),我自己写的。

      来源:https://firebase.google.com/docs/firestore/storage-size

      <!DOCTYPE html>
      <html>
        <head>
          <title>Calculte Firestore Size</title>
        </head>
        <body>
        <h1>Firestore Document Size Calculator</h1>
          <h2 id="response" style="color:red">This is a Heading</h2>
          <textarea id="id" style="width: 100%" placeholder="Firestore Doc Ref"></textarea>
          <textarea id="json" style="width: 100%; min-height: 200px" placeholder="Firestore Doc Value JSON STRING"></textarea>
          <textarea id="quantity" style="width: 100%;" placeholder="How Many repeat this value?"></textarea>
          <script>
           document.getElementById("json").value='{"type": "Personal","done": false , "priority": 1 , "description": "Learn Cloud Firestore"}'
           document.getElementById("id").value = 'users/jeff/tasks/my_task_id'
           calculate()
           function yuzdeBul(total,number) {
              if (number == 0) {
                return 0;
              }
              const sonuc = Math.ceil(parseInt(number) / (parseInt(total) / 100));
              return sonuc;
            }
            function calculate(){
              var quantity = parseInt(document.getElementById("quantity").value || 1);
              var firestoreId = document.getElementById("id").value;
              var refTotal = firestoreId
                  .split("/")
                  .map((v) => v.length + 1)
                  .reduce((a, b) => a + b, 0) + 16;
              var idTotal = 0
                
              //console.log(idTotal);
              var parseJson = JSON.parse(document.getElementById("json").value);
              idTotal += calculateObj(parseJson);
              idTotal+=32;
              idTotal*=quantity; 
              idTotal+=refTotal;
              document.getElementById("response").innerHTML = idTotal + "/" + 1048576 + " %"+yuzdeBul(1048576,idTotal);
            }
            function calculateObj(myObj) {
              var total = Object.keys(myObj).map((key) => {
                var keySize = key.toString().length + 1;
                var findType = typeof myObj[key];
                //console.log(key,findType)
                if (findType == "string") {
                  keySize += myObj[key].length + 1;
                } else if (findType == "boolean") {
                  keySize += 1;
                }
                if (findType == "number") {
                  keySize += 8;
                }
                if (findType == "object") {
                  keySize += calculateObj(myObj[key]);
                }
                return keySize;
              });
              return total.reduce((a, b) => a + b, 0);
            }
            document.getElementById("json").addEventListener("change", calculate);
            document.getElementById("id").addEventListener("change", calculate);
            document.getElementById("quantity").addEventListener("change", calculate);
          </script>
        </body>
      </html>

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
      【解决方案3】:

      对于想要根据1 MiB(1,048,576 字节)配额的最大值检查文档大小的 Android 用户,我制作了一个库,可以帮助您计算:

      通过这种方式,您将能够始终保持在限制以下。这个库背后的算法是关于Storage Size的官方文档中解释的算法。

      【讨论】:

      • 它非常简单实用。
      • @Pooja 是的,确实如此。
      • 有什么方法可以在 Unity 中使用它吗?
      • @Jay 我不确定你是否可以在 Unity 中使用这个库。没试过。
      【解决方案4】:

      对于 Swift 用户,

      如果您想估计文档大小,那么我使用以下方法。返回文档的估计大小(以字节为单位)。它不是 100% 准确,但给出了可靠的估计。基本上只是将数据映射中的每个键、值转换为字符串并返回 String + 1 的总字节数。有关 Firebase 如何确定文档大小的详细信息,您可以查看以下链接:https://firebase.google.com/docs/firestore/storage-size

      func getDocumentSize(data: [String : Any]) -> Int{
              
              var size = 0
              
              for (k, v) in  data {
                  
                  size += k.count + 1
                  
                  if let map = v as? [String : Any]{
                      size += getDocumentSize(data: map)
                  } else if let array = v as? [String]{
                      for a in array {
                          size += a.count + 1
                      }
                  } else if let s = v as? String{
                      size += s.count + 1
                  }
          
              }
              
              return size
              
          }
      

      【讨论】:

      • Firebase 还包括每个文档的“32 个额外字节”加上文档名称的大小(默认情况下约为 30),因此无论这个函数的总数是多少,都要加上 ~60。
      【解决方案5】:

      我发布了一个计算 Firestore 文档大小的 npm package

      其他计算 JS 对象大小的包如 sizeofobject-sizeof 不会为您提供精确的结果,因为 Firestore 中的某些原语具有不同的字节值。例如,Js 中的布尔值以 4 个字节存储,在 Firestore 文档中为 1 个字节。 Null 为 0 字节,在 Firestore 中为 1 字节。

      此外,Firestore 还拥有自己的具有固定字节大小的独特类型:Geo point、Date、Reference。

      引用是一个大对象。 sizeof 之类的包将遍历 Reference 的所有方法/属性,而不是在这里做正确的事情。这是将文档名称的字符串值+它的路径+ 16个字节相加。此外,如果 Reference 指向父文档,sizeofobject-sizeof 将不会在此处检测到循环引用,这可能比不正确的大小带来更大的麻烦。

      【讨论】:

        【解决方案6】:

        我正在查看 Firebase 参考资料,希望元数据有一个属性,但事实并非如此。您可以查看here

        所以我的下一个方法是将物体的重量计算为近似值。 sizeOf library 似乎有一个合理的 API。

        所以它会是这样的:

        sizeof.sizeof(doc.data());
        

        我不会使用文档快照,因为它包含元数据,例如是否有待保存的保存。另一方面,在某些情况下,高估可能会更好。

        [更新] 感谢 Doug Stevenson 的精彩见解

        所以我很好奇实际上会有多大的差异,所以我用我笨拙的 js 做了一个肮脏的比较,你可以看到 demo here

        考虑这个对象:

         {
          "boolean": true,
          "number": 1,
          "text": "example"
          }
        

        id 打折,结果如下:

        | Method  | Bytes |
        |---------|-------|
        | FireDoc | 37    |
        | sizeOf  | 64    |
        

        所以如果我们想高估, sizeOf 库可能是一个很好的预测器(假设计算很好,并且对于更复杂的实体表现得或多或少相等)。但正如评论中所解释的,这是一个粗略估计

        【讨论】:

        • 是的。我也是这么期待的。但是什么也没找到。
        • 我不相信 sizeof 库可以准确表示 Firestore 文档的大小。内存中 JS 对象的大小将不同于 Firestore 中保存的文档的大小。 JS 对象的实现在不同的运行时可能会有很大的不同。我只会使用该库作为一个非常粗略的估计。我希望在大字符串值的情况下估计会更准确,而当有很多各种非基本类型的字段时,估计会不太准确。
        • @DougStevenson 更新了答案,很有趣,希望对您有所帮助
        【解决方案7】:

        用于计算文档大小的计算已完整记录在here。那里有很多文字,所以请导航到那​​里阅读。在这里复制所有文本是不值得的。

        如果您必须随着文档的增长手动计算文档的大小,我认为您可能没有对数据进行可扩展的建模。如果您有可以无限增长的数据列表,您可能不应该使用列表字段,而是将该数据放在新集合或子集合中的文档中。此规则有一些例外,但一般而言,您不必担心在客户端代码中计算文档的大小。

        【讨论】:

        • 有计划发布这些估算的代码吗?对于社区来说,这将是一件好事。
        • 在某些情况下,拥有此类数据会非常有用。例如,在具有大量交换的聊天应用程序的情况下,可以将消息批处理到更少的文档中以提高读取性能,直至达到安全值。聊天应用程序从 Firestore 加载单个响应的 Angular 聊天历史记录的当前加载时间还有很多不足之处。
        • 这是一个双刃剑,我们必须在担心不断增长的文档大小与不断增长的文档数量之间做出选择。将数据添加到一份文档将节省检索时间和成本(读取一份文档成本),但我们不得不担心文档大小。虽然将数据拆分到多个文档将有助于避免文档大小限制,但会增加检索时间和成本(读取多个文档成本)。 IMO,文档元数据中应该有一个文档大小的属性。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-09
        • 1970-01-01
        • 2018-08-15
        • 1970-01-01
        • 2019-05-05
        • 1970-01-01
        相关资源
        最近更新 更多