Firestore 文档的确切大小是多少? [英] What is the exact size of a Firestore document?

查看:21
本文介绍了Firestore 文档的确切大小是多少?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了计算实际上传的数据量,我们使用 Firebase 存储和计算

一个文档的大小是:

  • 文档名称大小
  • 每个字段名的字符串大小之和
  • 每个字段值的大小总和(我们只有一个字段
    这个例子)
  • 32 个额外字节

以下代码中,文档名'mountain_image'为14,字段名'imageData'为9,字段值大小计算(如下图)加上32个字节.

在此示例中,我已将 1Mb 图像拖到我的应用程序包中.这是读取该图像、将其转换为 Firestore 的 NSData 类型并上传文件的 (macOS) 代码.

func uploadImageToFiresre() {让 image = NSImage(imageLiteralResourceName: "Mountain.jpeg")守卫让 asTiffData = image.tiffRepresentation else { return }让数据 = NSData(数据:asTiffData)让 imgRep = NSBitmapImageRep(data: data as Data)守卫让 jpgData = imgRep?.representation(使用: NSBitmapImageRep.FileType.jpeg, 属性: [:]) else { return }让文档名称大小 = 14让 fieldNameSize = 9让 dataSize = jpgData.count让 addlSize = 32让 totalSize = docNameSize + fieldNameSize + dataSize + addlSize打印(允许的大小:(1048487)")打印(总大小:(总大小)")让 imageCollection = self.db.collection("images")让 thisImage = imageCollection.document("mountain_image")让 dict:[String:Any] = ["imageData": jpgData]thisImage.setData(dict, completion: { error in如果让错误 = 错误 {打印(err.localizedDescription)返回}print("上传成功")})}

控制台的输出是这个

允许的大小:1048487总大小:1040221上传成功

因此可以看出,总大小刚好低于 Firestore 文档中允许的大小.

总而言之,此代码将一个 1Mb 的文件上传到 Firestore 文档

为了完整起见,这里是读回该数据对象、转换回图像并显示在 UI 中的代码

func readImageFromFirestore() {让 imageCollection = self.db.collection("images")imageCollection.getDocuments(完成:{ 快照,错误在如果让错误 = 错误 {打印(err.localizedDescription)返回}守卫让快照=快照其他{返回}对于 snap.documents 中的文档 {让 imageData = doc.get("imageData") 作为!数据让图像 = NSImage(data: imageData)self.myImageView.image = 图像}})}

请记住,文本字符串的大小是 UTF-8 编码的字节数 + 1,因此Hello"总共为 6,5 + 1

OP 添加了一些关于存储地理点的附加信息.地理点是 Firestore 中的一种特定数据类型,需要一个字段来存储地理点.尝试在单个字段中存储多个地理点不是一种选择.

话虽如此,如果您想存储 1Mb 的地理点,仍然可以完成.

这里有一些数学计算:文档中允许的总字节数为 1048487,如果每个地理点使用 16 个字节,快速划分表明可以存储大约 65530 个地理点数据.

因此,如果我可以上传 65530 字节,则表明文档可以容纳大约 1Mb 的数据.对?这是执行此操作的代码

以下代码创建了近 65530 个地理点,将它们转换为字符串并将它们存储在单个 Firestore 文档中.

func uploadGeopoints() {var geoArray = [GeoPoint]()让点 = GeoPoint(纬度:1.0,经度:1.0)对于 i 在 0..<65530 {geoArray.append(point)}让 geoString = geoArray.map { String("($0.latitude)($0.longitude)") }让组合字符串 = geoString.joined()让 geoCollection = self.db.collection("geoStrings")让 thisGeoString = geoCollection.document()让 dict:[String: Any] = ["geoString":combinedString]thisGeoString.setData(dict, completion: { error in如果让错误 = 错误 {打印(err.localizedDescription)返回}print("上传成功")})}

The docs says that the size of a document is composed of:

  1. document name size
  2. The sum of the string size of each field name
  3. The sum of the size of each field value
  4. 32 additional bytes

The following document example:

  • "type": "Personal"
  • "done": false
  • "priority": 1
  • "description": "Learn Cloud Firestore"

Has the size of 147.

Question:

When calculating the size of a document, is there anything else I should care of? Perhaps some metadata? Because when using this calculation, there's for sure something missing.

I have this class:

class Points {
    public List<GeoPoint> geoPoints;

    public Points() {}

    public Points(List<GeoPoint> geoPoints) {
        this.geoPoints = geoPoints;
    }
}

And this is how I create the list and how I write it to the database:

List<GeoPoint> geoPoints = new ArrayList<>();
for (int i = 1; i <= 40_327 ; i++) {
    geoPoints.add(new GeoPoint(11.22, 33.44));
}
DocumentReference geoRef = db.collection("pointsgeo");
geoRef.set(new Points(geoPoints)).addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        if (task.isSuccessful()) {
            Log.d("TAG", "geoPoints added successfully");
        } else {
            Log.d("TAG", task.getException().getMessage());
        }
    }
});


Edit with example:

My reference is:

db.collection("points").document("geo");

  1. (6 + 1) + (3 + 1) + 16 = 27

The field name (the array) is called geoPoints

  1. 9 + 1 = 10

I store in that array 40,327

  1. 40,327 * 16 = 645,232

There is an additional 32 additional bytes for each document

  1. 32

So it makes a total of:

Total: 27 + 10 + 645,232 + 32 = 645,301 bytes

There is nowhere specified in the docs that each element in the array counts more than his length:

Field value size

The following table shows the size of field values by type.

Type Size

Array The sum of the sizes of its values

Even so, if I need to add a byte (bytes) for every position, for example, 1 for a one digit number, 2 for a two digit number and so on and an additional 1 byte as it is in case of Strings, I should add 230,850 to the total.

So it makes a new total of 645,301 + 230,850 = 876,153‬.

This is the maximum allowed. Adding 40,328, will be rejected.

Anyway it is again less than the maximum 1,048,576 allowed.

解决方案

TL;DR

The original question did not involve Geopoints but as more discussion took place that was the ultimate goal. The issue is not that Firestore Documents can't hold 1Mb of data (because they can as clearly shown below) but the actual issue is how the OP is calculating how much data they want to store.

A Geopoint takes 16 bytes but there is also the rest of the calculation that should be added in. So here's a summary to calculate the size of a document

docNameSize = 8 //suppose it's called 'geoArray'
fieldNameSize = 5 // this is an array, so the first element name is 0 = 1 byte, 
                  // element 10 name would be two bytes
                  // up to 5 bytes for the higher numbers
geoPointSize = 16 * number of geopoints
addlSize = 32

So suppose there are 1000 geopoints

8 + (bytes depending on the field name length) + (16 * # of geopoints) + addl Size

So as you can see, the discussion is not around how much data a document will hold but about how the document size for a geopoint is calculated.

quick calculation

var s = ""
for i in 0..<10000 {
    s += String(i)
}
print(s.count)

shows that if you want to store 10000 Geopoints, 38890 bytes goes just to field names alone.

Discussion

This answer shows how to calculate the size of a Firestore document as well as the code to demonstrate how a file (an image in this case) of size 1Mb can be uploaded to a Firestore document.

Note that this is NOT how it should be done in real world use! - images and files should be stored in Storage, not Firestore, so take this as an example case.

An additional note that storing datasets that max out the capacity of a document may hinder overall performance and negates the ability to query or sort that data server side which puts a lot more strain on the apps resources. If there is concern about cost per number of writes/reads, I suggest looking at the Real Time Data Base as the costs are per amount of data, not reads/writes.

First we start with a 1Mb jpg called Mountain

To calculate the actual amount of data being uploaded, we use the following from the Firebase Storage and Calculations

The size of a document is the sum of:

  • The document name size
  • The sum of the string size of each field name
  • The sum of the size of each field value (we have only one field in
    this example)
  • 32 additional bytes

In the following code, the document name is 'mountain_image' which is 14, the field name is 'imageData' 9, the size of the field value is calculated (shown below) plus 32 bytes.

For this example, I've dragged the 1Mb image into my App bundle. Here's the (macOS) code that reads that image, converts it to a NSData type for Firestore and uploads the file.

func uploadImageToFirestre() {
    let image = NSImage(imageLiteralResourceName: "Mountain.jpeg")

    guard let asTiffData = image.tiffRepresentation else { return }
    let data = NSData(data: asTiffData)

    let imgRep = NSBitmapImageRep(data: data as Data)
    guard let jpgData = imgRep?.representation(using: NSBitmapImageRep.FileType.jpeg, properties:  [:]) else { return }

    let docNameSize = 14
    let fieldNameSize = 9
    let dataSize = jpgData.count
    let addlSize = 32

    let totalSize = docNameSize + fieldNameSize + dataSize + addlSize

    print("allowed size: (1048487)")
    print("total size:   (totalSize)")
    let imageCollection = self.db.collection("images")
    let thisImage = imageCollection.document("mountain_image")
    let dict:[String:Any] = ["imageData": jpgData]
    thisImage.setData(dict, completion: { error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        print("upload success")
    })
}

the output to console is this

allowed size: 1048487
total size:   1040221
upload success

So as can be seen, the total size is just under the allowed size in a Firestore document.

To summarize, this code uploads a 1Mb file to a Firestore Document

For completeness, here's the code that reads back that data object, converts back to an image and displays in the UI

func readImageFromFirestore() {
    let imageCollection = self.db.collection("images")
    imageCollection.getDocuments(completion: { snapshot, error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        guard let snap = snapshot else { return }

        for doc in snap.documents {
            let imageData = doc.get("imageData") as! Data
            let image = NSImage(data: imageData)
            self.myImageView.image = image
        }

    })
}

Keep in mind that Text Strings sizes are the number of UTF-8 encoded bytes + 1 so 'Hello' would be 6 total, 5 + 1

EDIT:

The OP added some additional information about storing Geopoints. A Geopoint is a specific data type in Firestore and requires a single field to store a geopoint. Attempting to store multiple geopoints in a single field is not an option.

That being said, if you want to store 1Mb of geopoints, it can still be done.

Here's some math: the total bytes allowed in a document is 1048487 and if each geopoint uses 16 bytes, quick division shows that approximately 65530 worth of geopoint data can be stored.

So if I can upload 65530 bytes then it shows that a document can hold approximately 1Mb of data. Right? Here's the code that does that

The following code creates almost 65530 geopoints, converts them to a string and stores them in a single Firestore document.

func uploadGeopoints() {
    var geoArray = [GeoPoint]()
    let point = GeoPoint(latitude: 1.0, longitude: 1.0)
    for i in 0..<65530 {
        geoArray.append(point)
    }

    let geoString = geoArray.map { String("($0.latitude)($0.longitude)") }

    let combinedString = geoString.joined()

    let geoCollection = self.db.collection("geoStrings")
    let thisGeoString = geoCollection.document()
    let dict:[String: Any] = ["geoString": combinedString]
    thisGeoString.setData(dict, completion: { error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        print("upload success")
    })
}

这篇关于Firestore 文档的确切大小是多少?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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