Query firestore database on timestamp field - firebase

I'm relatively new with firestore (and programming) and wasn't able to find a solution to my problem online.
Looking to query documents in an existing collection. The documents all have a timestamp field.
When I attempt to query for all documents ">" or "<" right now, the query works fine. When I attempt to query for ">" or "<" 7 days ago, the query returns nothing. I'm sure that I'm probably just missing something small. Thanks for any help!
These return documents as expected:
var today = new Date();
db.collection("****").where('display', '==', true).where('createdAt', '>', today).get().then(function(querySnapshot) {
and
var today = new Date();
db.collection("****").where('display', '==', true).where('createdAt', '<', today).get().then(function(querySnapshot) {
These don't return anything:
var today = new Date()-604800000;
db.collection("****").where('display', '==', true).where('createdAt', '>', today).get().then(function(querySnapshot) {
and
var today = new Date();
db.collection("****").where('display', '==', true).where('createdAt', '>', today-604800000).get().then(function(querySnapshot) {
and just for the heck of it
var today = new Date()-1;
db.collection("****").where('display', '==', true).where('createdAt', '>', today).get().then(function(querySnapshot) {
I've seen others request a look at what the field looks like in Firestore so here is a pic:
sorry it's a link
Please let me know if there is anything else that might be helpful. Thanks!
EDIT TO SHOW NEXT ATTEMPT:
var config = {****};
firebase.initializeApp(config);
const db = firebase.firestore();
const settings = {/* your settings... */ timestampsInSnapshots: true};
db.settings(settings);
var today = new Date();
var yesterday = date.setDate(today.getDate() - 1);
db.collection("****")
.where('display', '==', true)
.where('createdAt', '>', yesterday)
.get()
.then(function(querySnapshot) {console.log(createdAt)});

Ok. So I got some assistance from a very helpful Google developer.
This ended up working.
var beginningDate = Date.now() - 604800000;
var beginningDateObject = new Date(beginningDate);
db.collection("****")
.where('display', '==', true)
.where('createdAt', '>', beginningDateObject)
.get()
.then(function(querySnapshot) {console.log(/* ... */)});

Related

Firestore query between two timestamps [duplicate]

I need the help to query long collection with date range. See the below example document. I wanna query startTime field using date range.
Since I have the dueDate field stored as "timestamp" (and NOT as string or number) on Cloud Firestore, I did this to get the invoice documents with a due date on 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)
);
NOTE: dueDate field was stored at firebase with a Date() object. e.g.: this.doc.dueDate = new Date('2017-12-25')
You could store the datetime object as Unix time (seconds since 1 January 1970). Then you can simple use the where select like this:
collectionRef.where("startTime", ">=", "1506816000").where("startTime", "<=", "1507593600")
Btw - to convert from datetime to Unix time in your app, you can use the excellent (now deprecated) library moment (if you are building something with js or node).
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)
});
const event = new Date();
const expirationDate = admin.firestore.Timestamp.fromDate(event);
const query = collectionRef.where('startTime', '<=', expirationDate)
As startTime stored as Timestamp, you can do this query range for more accururate (this good for both condition of long date range or same date range).
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
});
I used this in my Node.js apps. Hopefully this useful.
For everyone recently using Firebase Firestore, there's a difference depending on your settings of your Firebase implementation (depending on the firebase version).
Before, Firestore was saving Timestamp as a Date, however as described here in the docs the will be replaced soon by a Timestamp object. See the Timestamp docs here.
You can force your implementation already by adding a setting in your code to force Firebase to use Timestamp objects instead of Date like this example:
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);
The solution is to use Date.now(). Stop using timestamp service from Firebase, you need to work with the numerical value of the time in milliseconds like for example: 1514271367000, instead if Firestore uses 26/12/2017 1:56:07 GMT- 0500 (-05) will not work. An example of a query is:
this.fsService.afs.collection('chats/4bY1ZpOr1TPq8bFQ3bjS/finance/123+finance/12345'
, ref => ref.orderBy('hour').startAt(1514184967000).endAt(1514271367000))
.valueChanges().subscribe(data =>{
this.mensajes = data;
})
Those who, like me, are using PHP to access Firestore, can do something like this:
$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();
Enjoy.
Generic function to find documents in a collection by date range of specifics fields:
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();
}
Packages:
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;
In a frontend application, this is how Firebase timestamps and dates can be used to query and store documents.
What worked for me was
Format Date with Moment JS and split into Day, Month & Year
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();
I think this will help you out,
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"]);
}),
},
);
}
now you need to use these queries for filtering documents with conditions
because .where() is not working for me
db.collection("id").whereGreaterThan("field","value")
.whereEqualTo("field","value")
.whereLessThen("field","value")

How to retrieve data based on latest timestamp

I'm currently studying how to retrieve data using Firebase specifically using Cloud Firestore. I have created a sample database like this
So the question is how we retrieve the announcements fields based on created timestamp which is created_at field in descending order?
I have followed this Order and limit data with Cloud Firestore but the syntax does not include document reference which means it only can order by document id in the collection but not by document's fields right?
Here is my current code looks like
final announcementList = <AnnouncementModel>[].obs;
getAnnouncements() async {
announcementList.value = [];
final snapshot = await firestore.collection("announcements").doc("announcements").get();
final data = snapshot.data()!['announcements'] as List<dynamic>;
for (var i = 0; i < 5; i++) {
announcementList.add(AnnouncementModel(
title : data[i]['title'],
desc : data[i]['desc'],
logo : data[i]['logo'],
link : data[i]['link'],
createdAt : data[i]['created_at'],
));
}
announcementList.refresh();
}
The expected output that I want is to retrieve only top 5 latest created announcements.
The code that I have tried but returns nothing.
test() async{
final snapshot = await firestore.collection('announcements').orderBy('created_at',
descending: true).limit(5).get();
final data = snapshot.docs.map((e) => e.data());
print('Output $data');
}
//OUTPUT
Output ()
you can try orderby with desc
take refrence from the below code
db.collection("devs")
.orderBy("timestamp", "desc")
.onSnapshot((snapshot) => {
/_ your magic goes here _/;
});
this.subscribe = firebase
.firestore()
.collection('orders')
.where('restaurant_code', '==', this.state.restaurantCode)
.orderBy('timestamp', 'desc')
.onSnapshot((docSnapshot) => {
const dataSource = [];
docSnapshot.forEach((doc) => {
dataSource.push(doc.data());
});
if (this._isMounted) {
this.setState({ dataSource });
}
});
here is link to follow might help
Firestore orderBy Timestamp DESC

Query a document value in a nested collection in firebase

I need to get the values from a document with this schema in Firebase:
COLLECTION => DOCUMENT => COLLECTION => DOCUMENT
userPolls => userId => dailyPolls => 20200825 => pollDate: "2020/08/25"
status: "Under PUM"
statusCode: "pum"
uid: "zwQnrrBdNCemWyXEW2LHmw8LejA2"
This is my attempt at it. But I think I am getting it wrong in flutter
final CollectionReference userPollCollection =
Firestore.instance.collection('userPolls');
Future getPoll() async {
final DateTime now = DateTime.now();
final DateFormat formatter = DateFormat('yyyy/MM/dd');
final String formatted = formatter.format(now);
var pollDate = formatted;
var docRef = await applicationUser
.document(userId)
.collection('dailyPolls')
.document(pollDate);
docRef.get().then((onValue) => {print(onValue.data['status'])});
}
I know that this is not right. Can you please show me how? Thank you.
EDIT
For reference, this is how I ADD data to the firestore db:
Future setPoll(UserPoll userPoll) async {
var dt = userPoll.pollDate.replaceAll('/', '');
return await userPollCollection
.document(userId)
.collection('daillyPolls')
.document(dt)
.setData({
'uid': userId,
'pollDate': userPoll.pollDate,
'status': userPoll.status,
'statusCode': userPoll.statusCode
});
}
This is how I try to get it
Future getPoll() async {
final DateTime now = DateTime.now();
final DateFormat formatter = DateFormat('yyyy/MM/dd');
final String formatted = formatter.format(now);
var pollDate = formatted;
var dt = pollDate.replaceAll('/', '');
var docRef = userPollCollection
.document(userId)
.collection('dailyPolls')
.document(dt);
docRef.get().then((onValue) {
print(onValue.data);
});
}
}
If I use this code based on the help of Peter Haddad, I get a null value when printing my result.data
You have to do the following:
var docRef = Firestore.instance.collection("userPolls").document(userId).collection('dailyPolls').where("pollDate", isEqualTo: pollDate);
var result = await docRef.getDocuments();
result.documents.forEach((result) {
print(result.data);
});
});
Since pollDate is an attribute inside a document then you can use the where() method to query and get the document

Flutter Firebase timestamp searchquery

In my apps user can post. And post store in firebase like this
I wanna fetch my all post which posted in last week. I need some filter in my search query. But I dont know how can I.
this my search query
_newQuerySnapshot = await Firestore.instance
.collection("posts")
.orderBy("createdAt", descending: true)
.startAfterDocument(lastDocument)
.limit(5)
.getDocuments();
I need like this .where( //posted in last week )
Please help me .
I solved like this.
var beginningDate = DateTime.now();
var newDate=beginningDate.subtract(Duration(days: 1));
_newQuerySnapshot = await Firestore.instance
.collection("posts").where("createdAt",isGreaterThanOrEqualTo: newDate)
.orderBy("createdAt", descending: true)
.limit(5)
.getDocuments();
Or you can do like this
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)
});
You can use where query in firestore, https://firebase.google.com/docs/firestore/query-data/queries#query_operators

Reading data out of datastore with dialogflow

I'm doing a chatbot similar to helpdesk (Dialogflow - inline editor). I'm able to write to datastore but I`m facing some issues with read out of data, it is a basic operation of finding UserID but code is not kicking off -please help code below.
const Datastore = require('#google-cloud/datastore');
const datastore = new Datastore({
projectId: 'bot-datastore-mnddjv'
});
function write(agent) {
var name = agent.parameters.name;
var sur = agent.parameters.sur;
var uid = agent.parameters.uid;
const taskKey = datastore.key('Key');
const entity = {
key: taskKey,
data: {
name: name,
sur: sur,
uid: uid
}
};
return datastore.save(entity).then(() => {
console.log(`Saved ${entity.key.name}: ${entity.data.item_name}`);
agent.add(`Stored ${name},${sur}`); -----> That part is working
});
}
function read(agent){
const query = datastore.createQuery('Key').filter('name');
return datastore.runQuery(query).then(() =>{
const sortA = query.order('name');
const sortD = query.order('name',( {descending:true}));
agent.add("Scores: ",sortA); ----// This funcion is not working
});
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('Zapis', write);
intentMap.set('Odczyt', read);
agent.handleRequest(intentMap);
});
The issue seems to be in your usage of filter().
You need to use an operator like =, > etc. so if that condition is met the query will run.
Here is a sample code from the documentation.
const query = datastore
.createQuery('Task')
.filter('done', '=', false)
.filter('priority', '>=', 4)
.order('priority', {
descending: true,
});

Resources