Запретить перезапись createdAt и updatedAt в облачной функции, когда набор объектов включает их - PullRequest
0 голосов
/ 08 мая 2020

Я пишу код Node.js для импорта данных из существующей базы данных в Firebase Cloud Firestore. Мы создали даты createdAt и updatedAt, которые я хочу сохранить в переходе. Проблема в том, что мы создали облачные функции, чтобы автоматически устанавливать их при создании объекта, поэтому он всегда перезаписывает значение объекта текущей меткой времени. Если я снова запустил наш скрипт импорта, таким образом, set обновляет существующий документ, значения createdAt и updatedAt в объекте сохраняются.

Как я могу заставить его использовать указанные значения и не перезаписывать их текущей меткой времени при создании?

const oldNote = {
  id: "someid",
  text: "sometext",
  createdAt: new Date(2018, 11, 24, 10, 33, 30, 0),
  updatedAt: new Date(2018, 11, 24, 10, 33, 30, 0)
}

const note = {
  text: oldNote.text,
  createdAt: firebase.firestore.Timestamp.fromDate(oldNote.createdAt),
  updatedAt: firebase.firestore.Timestamp.fromDate(oldNote.updatedAt)
};
firestoredb.collection("notes").doc(oldNote.id).set(note).then((docRef) => {
    //FIXME: createdAt and updatedAt aren't preserved, always today
}).catch((error) => {
    console.error("Error setting user: ", error);
});

Вот облачные функции:

exports.updateCreatedAt = functions.firestore
.document("{collectionName}/{id}")
.onCreate((snap, context) => {
    const now = admin.firestore.FieldValue.serverTimestamp();

    return snap.ref.set(
        {
            createdAt: now,
            updatedAt: now
        },
        { merge: true }
    );
});

exports.updateUpdatedAt = functions.firestore
.document("{collectionName}/{id}")
.onUpdate((change, context) => {
    const newValue = change.after.data();
    const previousValue = change.before.data();

    if (
        Boolean(newValue.updatedAt) &&
        Boolean(previousValue.updatedAt) &&
        newValue.updatedAt.isEqual(previousValue.updatedAt)
    ) {
        const now = admin.firestore.FieldValue.serverTimestamp();

        return change.after.ref.set({ updatedAt: now }, { merge: true });
    } else {
        return false;
    }
});

Ответы [ 2 ]

0 голосов
/ 08 мая 2020

Я пошел дальше и развернул обновление для триггера onCreate в Google Cloud Console. Теперь он проверяет, содержит ли объект уже createdAt и / или updatedAt, и использует их вместо перезаписи, если это так.

exports.updateCreatedAt = functions.firestore
.document("{collectionName}/{id}")
.onCreate((snap, context) => {
    const now = admin.firestore.FieldValue.serverTimestamp();
    const createdAt = snap.data().createdAt != undefined ? snap.data().createdAt : now;
    const updatedAt = snap.data().updatedAt != undefined ? snap.data().updatedAt : now;

    return snap.ref.set(
        {
            createdAt: createdAt,
            updatedAt: updatedAt
        },
        { merge: true }
    );
});
0 голосов
/ 08 мая 2020

Как видно из документации API для Timestamp.fromDate () принимает объект Date и преобразует его в объект Timestamp. Однако вы передаете ему объект Timestamp (если ваше редактирование не является подделкой значений, которые не были получены из записи базы данных в облачных функциях). Это ненужное преобразование, и, скорее всего, оно просто возвращает текущее время вместо ожидаемого. Просто используйте значения метки времени на месте:

const note = {
  text: oldNote.text,
  createdAt: oldNote.createdAt,
  updatedAt: oldNote.updatedAt
};

Имейте в виду, что когда вы записываете дату в Firestore, она сохраняет метку времени внутри. Это не вернется как свидание.

...