按日期范围查询 Firestore

Posted

技术标签:

【中文标题】按日期范围查询 Firestore【英文标题】:Firestore query by date range 【发布时间】:2018-04-10 13:59:23 【问题描述】:

我需要帮助来查询具有日期范围的长集合。请参阅以下示例文档。我想使用日期范围查询 startTime 字段。

【问题讨论】:

所有这些答案都有一个巨大的缺陷:一个查询只能包含“>”或“ 【参考方案1】:

由于我在 Cloud Firestore 上将 dueDate 字段存储为“时间戳”(而不是 stringnumber),因此我这样做是为了获取发票文档截止日期为 2017 年:

let start = new Date('2017-01-01');
let end = new Date('2018-01-01');

this.afs.collection('invoices', ref => ref
  .where('dueDate', '>', start)
  .where('dueDate', '<', end)
);

注意: dueDate 字段与 Date() 对象一起存储在 firebase。例如:this.doc.dueDate = new Date('2017-12-25')

【讨论】:

如果您对 Firestore 进行截图,是否可以从那里直观地分辨出日期时间对象或字符串之间的区别? 是的@DauleDK 看:imgur.com/a/draQo 第三个字段填充了一个 Date() js 对象,并存储为时间戳(firebase 进行了转换)。在图像上,您将看到格式化为 UTC 的时间戳,但我将其保存为 Date 对象。最后要检查这是否真的是一个时间戳字段,只需悬停该字段即可。就我而言,我看到“Marca de tiempo”,意思是“时间戳”。 哇,这太棒了 - 绝对应该添加到 firestore 查询文档中。我有这种感觉,我们将看到 firebase-firestore 控制台的许多更新。 “Marce de tiempo”——今天学到的最有价值的一课,谢谢 ;) 朋友们,我试过了,但没有任何回报 另外,如果您使用额外的等价查询 '==',您可能需要启用复合索引,最好的方法是捕获错误,这将输出 Firebase 链接您可以按照它来自动设置索引。我的请求看起来像这样,需要一个复合索引:.where('team_id', '==', teamId).where('time', '&gt;=', start).where('time', '&lt;=', end)【参考方案2】:

您可以将 datetime 对象存储为 Unix time(自 1970 年 1 月 1 日以来的秒数)。然后你可以像这样简单地使用 where select:

collectionRef.where("startTime", "&gt;=", "1506816000").where("startTime", "&lt;=", "1507593600")

顺便说一句 - 要在您的应用程序中从日期时间转换为 Unix 时间,您可以使用出色的(现已弃用)库 moment(如果您正在使用 js 或节点构建一些东西)。

【讨论】:

谢谢,但我已经有了日期格式的数据,就像随附的屏幕截图一样 好的。根据firebase datetime 是firestore中支持的数据类型。 startTime 是字符串还是日期时间对象? 它是 dateTime 对象它不是字符串 您能否从 Firebase 控制台截取屏幕截图 - 将鼠标悬停在 startTime 上方 - 看看日期时间是否像这里 imgur.com/a/draQo 添加到质疑新截图,似乎数据时间是我使用矩模块创建字段时的时间戳【参考方案3】:
    var startfulldate = admin.firestore.Timestamp.fromDate(new Date(1556062581000));
    db.collection('mycollection')
      .where('start_time', '<=', startfulldate)
      .get()
      .then(snapshot =>               
            var jsonvalue: any[] = [];
            snapshot.forEach(docs => 
              jsonvalue.push(docs.data())
               )
                 res.send(jsonvalue);
                 return;
                ).catch( error => 
                    res.status(500).send(error)
                );

【讨论】:

太棒了!你救了我的命。我刚刚用 firebase.firestore 替换了 admin.firestore,它起作用了。 这对我帮助很大。我不敢相信 Firebase 上没有包含查询日期的文档...【参考方案4】:
const event = new Date();
const expirationDate = admin.firestore.Timestamp.fromDate(event);
const query = collectionRef.where('startTime', '<=', expirationDate)

【讨论】:

谢谢你,这对我有帮助!【参考方案5】:

对于最近使用 Firebase Firestore 的每个人,根据您的 Firebase 实施设置(取决于 Firebase 版本)会有所不同。

以前,Firestore 将 Timestamp 保存为 Date,但正如 here in the docs 所述,很快将被 Timestamp 对象替换。请参阅Timestamp docs here。

您可以通过在代码中添加设置强制 Firebase 使用 Timestamp 对象而不是 Date 来强制实施,如下例所示:

var firebaseApp = firebase.initializeApp(
    apiKey: [APIKEY],
    authDomain: [FIREBASEAPPDOMAIN],
    projectId: [PROJECTID]
);

var firestore = firebase.firestore();
var settings =  timestampsInSnapshots: true ; // force Timestamp instead of Date
firestore.settings(settings);

【讨论】:

这实际上已被弃用,将在未来的版本中删除。 Firebase 希望您今后专门指定 Timestamp 对象。【参考方案6】:

由于startTime存储为Timestamp,您可以这样查询范围更准确(这对长日期范围或相同日期范围的情况都有好处)。

const start = new Date('2021-01-01T00:00:00.000z');
const end = new Date('2021-03-01T23:59:59.000z');

db.collection('Data').where('startTime', '>=', start).where('startTime', '<=', end).get().then(data => 
   //pass your 'data' here
);

我在我的 Node.js 应用程序中使用了它。希望这有用。

【讨论】:

【参考方案7】:

解决方案是使用 Date.now()。停止使用 Firebase 的时间戳服务,您需要使用以毫秒为单位的时间数值,例如:1514271367000,如果 Firestore 使用 26/12/2017 1:56:07 GMT-0500 (-05) 将不起作用.查询示例如下:

this.fsService.afs.collection('chats/4bY1ZpOr1TPq8bFQ3bjS/finance/123+finance/12345'
          , ref => ref.orderBy('hour').startAt(1514184967000).endAt(1514271367000))
          .valueChanges().subscribe(data =>
            this.mensajes = data;
          )

【讨论】:

Firestore 将 Date.now() 保存为数字数据可以吗?我觉得在某些情况下约会会更好,因为这和易于理解。 这似乎是 Firebase 实时数据库代码(例如,它使用 startAtendAt)而不是 Firestore 代码(将使用 where,请参阅 here)。两者相似,但又不相同。 时区的想法是什么。当我确定数字时,我应该将日期时间转换为 GMT 吗?【参考方案8】:

像我一样使用 php 访问 Firestore 的人可以这样做:

$startTime = new DateTime('2020-05-23 00:00:00');
$endTime = new DateTime('2020-06-23 23:59:59');

$start = new Google\Cloud\Core\Timestamp($startTime);
$end = new Google\Cloud\Core\Timestamp($endTime);

// fb is a Google\Cloud\Firestore\FirestoreClient object
$this->query = $this->fb->collection('your_collection');

$aux = $this->query;
$aux = $aux->where('startTime', '<', $end);
$aux = $aux->where('startTime', '>', $start);

return $aux->documents();

享受吧。

【讨论】:

【参考方案9】:

我想这会对你有所帮助,

yourMethod() 
    var date = DateTime.now();//
    print("First Date > " + DateTime(date.year, date.month, 1).toString());
    var datex = new DateTime(date.year, date.month + 1, 0);
    print("Last Date > " +datex);//
    //
    Firestore.instance
        .collection('biling')
        .where("driverId", isEqualTo: widget.uid)
        .where("date",
            isGreaterThanOrEqualTo:
                new DateTime(date.year, date.month, 1).toString())//1
        .where("date", isLessThanOrEqualTo: datex.toString())//2
        .orderBy('date', descending: true)
        .getDocuments()
        .then(
          (QuerySnapshot snapshot) => 
            snapshot.documents.forEach((f) 
              if (this.mounted) 
                setState(() 
                  totalP += double.tryParse(f.data["price"]);
                );
              
              print("_price " + f.data["price"]);
              print("_duePaymntForCompay " + f.data["duePaymntForCompay"]);
            ),
          ,
        );
  

【讨论】:

【参考方案10】:

按特定字段的日期范围在集合中查找文档的通用函数:

public List<QueryDocumentSnapshot> findDocsByDateRange(
                                          String collection, 
                                          String fieldStartDate,
                                          String fieldEndDate,
                                          Date startDate, 
                                          Date endDate) 
    ApiFuture<QuerySnapshot> querySnapshot = fireStore()
        .collection(collection)
            .whereGreaterThanOrEqualTo(FieldPath.of(fieldStartDate), startDate)
                .whereLessThanOrEqualTo(FieldPath.of(fieldEndDate), endDate)
                    .get();
    return querySnapshot.get().getDocuments();

包:

import com.google.api.core.ApiFuture;
import com.google.cloud.firestore.DocumentSnapshot;
import com.google.cloud.firestore.FieldPath;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.QueryDocumentSnapshot;
import com.google.cloud.firestore.QuerySnapshot;

【讨论】:

【参考方案11】:

在前端应用程序中,这就是 Firebase 时间戳和日期可用于查询和存储文档的方式。

【讨论】:

你好。尽可能多的外部链接可能有用,请将您的答案内容直接插入 SO。【参考方案12】:

对我有用的是 使用 Moment JS 格式化日期并拆分为日、月和年

const currentDate = moment().format("DD-MM-YYYY").split("-");
const currentDay = currentDate[0];
const currentMonth = currentDate[1];
const currentYear = currentDate[2];


const allDocuments = await collectionRef
.doc(docId)
.collection(*COLLECTION NAME*)
.where(
  *DATE PARAMETER NAME*,
  ">=",
  new Date(`$currentYear-$currentMonth-$currentDay`)
)
.where(
  *DATE PARAMETER NAME*,
  "<",
// $parseInt(currentDay) + *Number of days you want in range* 
  new Date(`$currentYear-$currentMonth-$parseInt(currentDay) + 1`)
)
.get();

【讨论】:

以上是关于按日期范围查询 Firestore的主要内容,如果未能解决你的问题,请参考以下文章

查询按日期范围分隔的行数

如何编写按日期范围和维度成员值进行切片的 mdx 查询

按日期范围分区 PostgreSQL 扫描所有分区

如何按日期(范围键)查询 DynamoDB,没有明显的哈希键?

按日期查询DynamoDB

按日期范围历史生成完整的类别结构