【问题标题】:Can't fetch data from firebase using Timestamp无法使用时间戳从 Firebase 获取数据
【发布时间】:2025-12-12 20:30:01
【问题描述】:

我正在尝试使用createdAt 属性从我的集合中获取一个值,该属性是一个时间戳。 这大致是我的查询的样子:

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

但是,当我运行它时,我收到以下错误:

错误是“FirebaseError:[code=invalid-argument]:使用无效数据调用的函数 Query.where()。不支持的字段值:自定义 Timestamp 对象。 Stacktrace 是“FirebaseError:使用无效数据调用的函数 Query.where()。不支持的字段值:自定义 Timestamp 对象

我非常困惑,我总是在其他集合中使用 Timestamp 对象来获取,如果我尝试只使用 date 对象,它就不起作用。我是不是忘记了什么?

编辑:根据要求,这是我的文档的示例:

{
  name: "My Data Name", // (string)
  createdAt: November 9, 2018 at 8:40:45 PM // (Timestamp)
}

【问题讨论】:

  • 示例文档记录是什么样的?
  • 您的括号与第二个 where 子句(带有 now 的那个)不匹配。这只是一个转录错误还是真的在代码中?
  • 当您可以忽略createdAt 是否小于或等于now 时,为什么还要检查它?虽然从逻辑上讲是有道理的,但数据不会存在于 now 之外,而只会浪费计算时间(和你的钱)。
  • @samthecodingman 添加不改变返回文档数量的任何类型的过滤器不会改变查询的成本。 Cloud Firestore 中的主要计费单位是读取的文档数。这也是查询性能的唯一指标。
  • @theJuls 您应该能够传递 Timestamp 或 Date 对象(将被转换为 Timestamp)。如果这些都不起作用,那么其他事情就很不对劲了。您使用的是什么版本的 SDK?

标签: javascript firebase google-cloud-firestore


【解决方案1】:

我有同样的问题。您需要检查两件事。

1。我是否使用了正确的 SDK?

您是否知道可以使用两种不同的 firebase SDK?一个是client SDKfirebase-js-sdk a.k.a. firebase package),另一个是firebase server SDKnodejs-firestore.a.k.a. @google-cloud/firebase package)。这两个库在 firestore.Timestamp 类上有自己的实现,它们不兼容

其他一些 NPM 包依赖如下:

"@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"

其中(*) 表示firestore.Timestamp 定义的位置。

简而言之,你应该使用相应的时间戳。

案例 1. 仅使用客户端 SDK

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

案例 2. 仅使用服务器 SDK

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

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

案例 3. 混合 SDK

当您测试在服务器上运行的代码(例如 firebase 函数)时,有时您需要使用客户端 SDK(特别是 @firebase/testing)。

// 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。我使用的版本是否正确?

如果您使用的是正确的 SDK,接下来要检查的是您是否使用了相同版本的 Timestamp 实现。例如,如果您使用 Client SDK,则应检查您的 package-lock.json 是否具有唯一版本的 firebase

就我而言,我在不同的时间安装了@firebase/testingfirebase,由于firebase@firebase/testing 的版本依赖性不同,我同时安装了两个不同的firebase 软件包。您可以更新旧软件包来解决此问题。

【讨论】: