theJuls
theJuls

Reputation: 7470

Can't fetch data from firebase using Timestamp

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

Answers (1)

Jongbin Park
Jongbin Park

Reputation: 739

I had the same issue. There are two things you need to check.

1. Am I using the right SDK?

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.

Case 1. Use a client SDK only

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();

Case 2. Use a server SDK only

import { firestore, initializeApp } from 'firebase-admin';

const app = initializeApp();
app.firestore().collection('users')
  .where('createdAt', '<=', firestore.Timestamp.fromDate(new Date()))
  .get();

Case 3. Mixing SDKs

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()
}));

2. Am I using the right version?

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

Related Questions