Я использую узел Пакет BigQuery для выполнения простой работы. Глядя на результаты (скажем, data
) задания, атрибут effective_date
выглядит так:
effective_date: BigQueryDate { value: '2015-10-02' }
который, очевидно, является объектом в возвращенном объекте data
.
Импорт возвращенного json в Firestore дает следующую ошибку:
UnhandledPromiseRejectionWarning: Error: Argument "data" is not a
valid Document. Couldn't serialize object of type "BigQueryDate".
Firestore doesn't support JavaScript objects with custom prototypes
(i.e. objects that were created via the 'new' operator).
Есть ли элегантный способ справиться с этим? Нужно ли перебирать результаты и преобразовывать / удалять все объекты?
Клиент firestore Node.js не поддерживает сериализацию пользовательских классов.
Более подробное объяснение вы найдете в этом выпуске:
https://github.com/googleapis/nodejs-firestore/issues/143
«Мы явно решили не поддерживать сериализацию пользовательских классов для веб-клиентов и клиентов Node.JS»
Решение состоит в том, чтобы преобразовать вложенный объект в простой объект. Например, используя lodash или JSON.stringify.
firestore.collection('collectionName')
.doc('id')
.set(JSON.parse(JSON.stringify(myCustomObject)));
Вот связанное сообщение:
Firestore: добавить настраиваемый объект в базу данных
Использование этого способа не позволяет вам устанавливать значения полей, такие как приращения и операции с массивами!
Также он разбивает типы даты.
Другой способ менее ресурсоемкий:
firestore
.collection('collectionName')
.doc('id')
.set(Object.assign({}, myCustomObject));
Примечание: работает только для объектов без вложенных объектов.
Также вы можете использовать class-transformer
и его classToPlain()
вместе с exposeUnsetFields
вариант, чтобы опустить значения undefined
.
npm install class-transformer
or
yarn add class-transformer
import {classToPlain} from 'class-transformer';
firestore
.collection('collectionName')
.doc('id')
.set(classToPlain(myCustomObject, {exposeUnsetFields: false}));
это работает лучше для меня, потому что, если у вас есть дата в вашем настраиваемом объекте, firestore повторно записывает ее как метку времени. Если вы выполните JSON.stringify (), ваша дата станет строкой, и это может стать кошмаром позже
@AndreCytryn Подробнее о проблемах сериализации дат можно прочитать здесь stackoverflow.com/questions/53520674/… и здесь stackoverflow.com/questions/10286204/…
Если у вас есть объект Timestamp
, не используйте JSON.parse(JSON.stringify(obj))
или classToPlain(obj)
, так как они повредят его при сохранении в Firestore.
Лучше использовать метод {...obj}
.
firestore
.collection('collectionName')
.doc('id')
.set({...obj});
Вероятно, вам нужно добавить
.doc()
в конец ссылки на firestore.