按日期范围查询 Firestore
Posted
技术标签:
【中文标题】按日期范围查询 Firestore【英文标题】:Firestore query by date range 【发布时间】:2018-04-10 13:59:23 【问题描述】:我需要帮助来查询具有日期范围的长集合。请参阅以下示例文档。我想使用日期范围查询 startTime 字段。
【问题讨论】:
所有这些答案都有一个巨大的缺陷:一个查询只能包含“>”或“ 【参考方案1】:由于我在 Cloud Firestore 上将 dueDate
字段存储为“时间戳”(而不是 string 或 number),因此我这样做是为了获取发票文档截止日期为 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', '>=', start).where('time', '<=', end)
【参考方案2】:
您可以将 datetime 对象存储为 Unix time(自 1970 年 1 月 1 日以来的秒数)。然后你可以像这样简单地使用 where select:
collectionRef.where("startTime", ">=", "1506816000").where("startTime", "<=", "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 实时数据库代码(例如,它使用startAt
和 endAt
)而不是 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的主要内容,如果未能解决你的问题,请参考以下文章