Reputation: 7470
I am trying to fetch a value from my collection using the createdAt
property, which is a timestamp.
This is roughly what my query looks like:
function getDataFromYesterdayToNow (db){
const now = new Date()
const yesterday = new Date(now.setDate(now.getDate() - 1))
yesterday.setHours(0, 0, 0, 0)
const { Timestamp } = firebase.firestore
return db
.collection('myData')
.where('createdAt', '>=', Timestamp.fromDate(yesterday))
.where('createdAt', '<=', Timestamp.fromDate(now))
.get()
}
However, when I run this, I get the following error:
error was 'FirebaseError: [code=invalid-argument]: Function Query.where() called with invalid data. Unsupported field value: a custom Timestamp object'. Stacktrace was 'FirebaseError: Function Query.where() called with invalid data. Unsupported field value: a custom Timestamp object
I am super confused, I have always fetched using Timestamp objects in other collections, and it does not work if I try to just use the date object. Have I forgotten something?
Edit: as requested, here is an example of what my doc looks like:
{
name: "My Data Name", // (string)
createdAt: November 9, 2018 at 8:40:45 PM // (Timestamp)
}
Upvotes: 4
Views: 757
Reputation: 739
I had the same issue. There are two things you need to check.
Did you know there are two different firebase SDK you can use? One is a client SDK (firebase-js-sdk a.k.a. firebase
package) and the other one is a firebase server SDK (nodejs-firestore .a.k.a. @google-cloud/firebase
package). These two libraries have its own implementation on firestore.Timestamp
class and THEY ARE NOT COMPATIBLE.
Some of the other NPM packages dependencies as follow:
"@firebase/firestore" (*)
-> "firebase" (client SDK which imports all @firebase/* except @firebase/testing)
-> "@angular/fire" (and other client libraries with firebase binding)
-> "@firebase/testing" (mocking Firestore client)
"@google-cloud/firebase" (*) (server SDK)
-> "firebase-admin"
-> "firebase-functions-test"
Where (*)
denotes the location of firestore.Timestamp
definition.
In short, you should use corresponding Timestamp.
import { firestore, initializeApp } from 'firebase';
import { config } from './my-firebase-config';
const app = initializeApp(config);
app.firestore().collection('users')
.where('createdAt', '<=', firestore.Timestamp.fromDate(new Date()))
.get();
import { firestore, initializeApp } from 'firebase-admin';
const app = initializeApp();
app.firestore().collection('users')
.where('createdAt', '<=', firestore.Timestamp.fromDate(new Date()))
.get();
Sometimes you need to use client SDK (specifically, @firebase/testing
) when you're testing code that are run on server (e.g. firebase functions.)
// server.ts
import { firestore, initializeApp } from 'firebase-admin';
const app = initializeApp();
app.firestore().collection('users')
.where('createdAt', '<=', fs.Timestamp.fromDate(new Date()))
.get();
// server.test.ts
import { firestore } from 'firebase';
import { initializeAdminApp } from '@firebase/testing';
// Replace server sdk with client sdk
jest.mock('firebase-admin', () => ({
firestore,
initializeApp: () => initializeAdminApp()
}));
If you're using the correct SDK, the next thing to check is whether you're using the same version of Timestamp implementation. If you're using Client SDK for example, then you should check your package-lock.json
whether it has a unique version of firebase
.
For my case, I installed @firebase/testing
and firebase
in a different time, and due to the difference firebase
version dependency from @firebase/testing
, I had two different firebase
packages installed at the same time. You can update an old package to fix this.
Upvotes: 2