Каков точный размер документа Firestore? - PullRequest
0 голосов
/ 08 апреля 2020

docs говорит, что размер документа состоит из:

  1. размер имени документа
  2. Сумма размера строки имя каждого поля
  3. Сумма размера каждого значения поля
  4. 32 дополнительных байта

Следующий пример документа:

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

Имеет размер 147.

Вопрос:

При расчете размера документа, есть ли что-то еще, о чем я должен заботиться ? Возможно, некоторые метаданные? Потому что при использовании этого вычисления наверняка чего-то не хватает.

У меня есть этот класс:

class Points {
    public List<GeoPoint> geoPoints;

    public Points() {}

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

И вот как я создаю список и как пишу это к базе данных:

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("points\geo");
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());
        }
    }
});

Редактировать с примером:

Моя ссылка:

db.collection("points").document("geo");
  1. (6 + 1) + ( 3 + 1) + 16 = 27

Имя поля (массив) называется geoPoints

9 + 1 = 10

Я храню в этом массиве 40,327

40,327 * 16 = 645,232

Для каждого документа есть дополнительные 32 байта

32

Таким образом, всего получается:

Всего: 27 + 10 + 645,232 + 32 = 645,301 байт

Нигде нет в документах указано, что каждый элемент в массиве имеет значение, превышающее его длину :

Размер значения поля

В следующей таблице показан размер значений поля по тип.

тип размер

массив сумма размеров его значений

четный Итак, если мне нужно добавить байт (байты) для каждой позиции, например, 1 для одного числа di git, 2 для числа двух di git и так далее, и дополнительный 1 байт, как он есть в В случае строк, я должен добавить 230,850 к итогу.

Таким образом, получается новое общее число 645,301 + 230,850 = 876,153.

Это максимально допустимый. Добавление 40328 будет отклонено.

В любом случае оно снова меньше , чем максимально допустимое значение 1,048,576.

1 Ответ

1 голос
/ 11 апреля 2020

TL; DR

Первоначальный вопрос не затрагивал геопоинтов, но по мере дальнейшего обсуждения это было конечной целью. Проблема не в том, что документы Firestore не могут содержать 1 МБ данных (потому что они могут, как ясно показано ниже), а в том, как операционный центр вычисляет, сколько данных они хотят сохранить.

Geopoint берет 16 байтов, но есть и остальные расчеты, которые следует добавить. Итак, вот сводная информация для расчета размера документа

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

Итак, предположим, что есть 1000 геоинтессий

8 + (в байтах в зависимости от длины имени поля) + (16 * число географических точек) + addl Размер

Итак, как вы можете видеть, речь идет не о том, сколько данных будет содержать документ, а о том, как документ вычисляется размер для геопункта.

быстрый расчет

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

показывает, что если вы хотите сохранить 10000 геопоинтов, 38890 байт идет только на имена полей.

Обсуждение

Этот ответ показывает, как рассчитать размер документа Firestore, а также код, чтобы продемонстрировать, как файл (в данном случае изображение) размером 1M b можно загрузить в документ Firestore.

Обратите внимание, что это НЕ так, как это должно быть сделано в реальных условиях! - изображения и файлы должны храниться в хранилище, а не в Firestore, поэтому возьмем это в качестве примера.

Дополнительное примечание, что хранение наборов данных, которые максимально используют емкость документа, может снизить общую производительность и свести на нет возможность запрашивать или сортировать данные на стороне сервера данных, что значительно увеличивает нагрузку на ресурсы приложений. Если существует озабоченность по поводу стоимости количества операций записи / чтения, я предлагаю рассмотреть базу данных в реальном времени, поскольку затраты относятся к объему данных, а не к операциям чтения / записи.

Сначала мы начнем с jpg размером 1 МБ, который называется Гора

enter image description here

Чтобы рассчитать фактический объем загружаемых данных, мы используем следующее из базы данных Firebase Хранение и расчеты

Размер документа представляет собой сумму:

  • Размер имени документа
  • Сумма размера строки каждого имени поля
  • сумма размера каждого значения поля (у нас есть только одно поле в
    этом примере)
  • 32 дополнительных байта

В следующем коде имя документа равно 'mountain_image ', то есть 14, имя поля' imageData '9, вычисляется размер значения поля (показано ниже) плюс 32 байта.

Для этого примера я перетащил изображение размером 1 МБ в свое приложение расслоение. Вот код (macOS), который считывает это изображение, преобразует его в тип NSData для Firestore и загружает файл.

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")
    })
}

вывод на консоль такой:

allowed size: 1048487
total size:   1040221
upload success

Можно увидеть, что общий размер чуть меньше разрешенного размера в документе Firestore.

Подводя итог, этот код загружает файл размером 1 МБ в документ Firestore

Для Для полноты, вот код, который считывает этот объект данных, преобразует обратно в изображение и отображает в пользовательском интерфейсе

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
        }

    })
}

Имейте в виду, что размеры текстовых строк - это число байтов в кодировке UTF-8 + 1, поэтому Всего «Привет» будет 6, 5 + 1

РЕДАКТИРОВАТЬ:

ОП добавил дополнительную информацию о хранении географических точек. Geopoint - это определенный тип данных c в Firestore, для которого требуется одно поле для хранения геопозиции. Попытка сохранить несколько геопоинт в одном поле не вариант.

При этом, если вы хотите сохранить 1 Мб геоинт, это все равно можно сделать.

Вот немного математики: Общее количество разрешенных байтов в документе - 1048487, и если для каждого геопункта используется 16 байтов, быстрое разделение показывает, что могут быть сохранены данные о приблизительно 65530.

Поэтому, если я могу выгрузить 65530 байтов, то это показывает, что документ может хранить около 1 МБ данных. Правильно? Вот код, который делает это

Следующий код создает почти 65530 геопоинт, преобразует их в строку и сохраняет их в одном документе Firestore.

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")
    })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...