Firestore按日期范围查询


Answers:


129

由于我在Cloud Firestore上将dueDate字段存储为“时间戳记”(而不是字符串数字),因此我这样做是为了获取截止日期为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')


1
如果您为Firestore截屏,是否可以从那里直观地看出datetime对象或字符串之间的区别?
DauleDK

是@DauleDK外观:imgur.com/a/draQo第三个字段中填充了Date()js对象,并将其存储为时间戳(firebase进行了转换)。在图像上,您将看到该时间戳记格式为UTC,但是我将其保存为Date对象。最后检查一下这是否是一个时间戳字段,只需将其悬停即可。就我而言,我看到的是“ Marca de tiempo”,意思是“时间戳记”。
Capy 2017年

3
哇,真棒-一定要添加到Firestore查询文档中。我有种感觉,我们将看到对Firebase-firestore控制台的许多更新。“ Marce de tiempo”-今天最有价值的教训,格拉西亚斯;)
DauleDK

2
朋友,我已经尝试过了,但是却什么也没返回
Nimer Farahty 17-10-30

另外,如果您使用其他等效查询'==',则可能需要启用复合索引,最好的方法是捕获错误,这将输出Firebase链接,您可以按照该链接进行自动设置索引。我的请求如下所示,并且需要一个Composite_index:.where('team_id', '==', teamId).where('time', '>=', start).where('time', '<=', end)
wdavies973

25

您可以将datetime对象存储为Unix时间(自1970年1月1日以来的秒数)。然后,您可以像下面这样简单地使用where选择:

collectionRef.where("startTime", ">=", "1506816000").where("startTime", "<=", "1507593600")

顺便说一句-要在应用程序中从datetime转换为Unix时间,您可以使用出色的库时间(如果您使用js或node进行构建)。


1
谢谢,但是我已经有日期格式的数据,就像所附的屏幕截图一样
Nimer Farahty

好。根据firebase,datetime是firestore中受支持的数据类型。startTime是字符串还是日期时间对象?
DauleDK

它是dateTime对象,不是字符串
Nimer Farahty

您可以从firebase控制台中截取屏幕截图-在此处将鼠标悬停在startTime上方-查看日期时间是否如此处所示imgur.com/a/draQo
DauleDK

添加到新屏幕快照问题中,当我使用矩模块创建字段时,数据时间似乎是时间戳记
Nimer Farahty 17-10-30

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

2
太好了!你救了我的命男。我只是将admin.firestore替换为firebase.firestore,并且可以正常工作。
Fox5150

11
const event = new Date();
const expirationDate = admin.firestore.Timestamp.fromDate(event);
const query = collectionRef.where('startTime', '<=', expirationDate)

6

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

之前,Firestore另存TimestampDate,但是如文档此处所述,该Timestamp对象很快就会被对象替换。请在此处查看时间戳文档

您可以通过在代码中添加一个设置来强制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);

1

像我这样使用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();

请享用。


1

解决方案是使用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;
          })

2
如果Firestore将Date.now()保存为数字数据,可以吗?我觉得在某些情况下约会会更好,因为这样并易于理解。
Telion

这似乎是Firebase实时数据库代码(例如,使用startAtendAt),而不是Firestore代码(将使用where,请参见此处)。两者相似,但不相同。
robsiemb

时区的想法是什么。确定数字后,应该将日期时间转换为格林尼治标准时间吗?
卡萨巴·托斯

0

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

Firestore日期用法


2
你好。尽可能使用外部链接,请将答案的内容直接插入到SO中。
Maciej Jureczko

0

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

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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.