Compare two Firestore Timestamps by "greater than" [duplicate] - firebase

This question already has an answer here:
Filter including field in formula
(1 answer)
Closed 3 years ago.
I'm trying to compare two timestamps inside a cloud function.
Not by "equality" (as described here) but by "greater than".
I do not know where is the problem, but I can't get it working.
This is my code, quite simple:
const lastDayUnread = await admin.firestore()
.collection('/unread')
.where('last_message', '>', 'last_seen')
.get()
I also tried using .seconds property but still nothing:
.where('last_message.seconds', '>', 'last_seen.seconds')
If I execute the same query from a JS client, it works, and teh console shows me that there is a Timestamp object inside my documents last_seen and last_message properties.

The right-hand side of a where clause in Cloud Firestore must be a literal value. There is no support for looking up the value of another field.
The typical workaround would be to store an additional field with last_message.seconds - last_seen.seconds and then:
.where('delta_seconds', '>', 0)

Related

Preventing magic numbers used in firebase realtime database

So I want to specify a time after which a post gets deleted. The time is 3 months, in my code I would define this as
const THREE_MONTHS_IN_MS = 7889400000
export const TIME_AFTER_WHICH_USER_IS_DELETED = THREE_MONTHS_IN_MS
How can I define this in my database without resorting to the use of a magic number? Basically it looks like this right now:
timeAfterWhichUserIsDeleted: 7889400000
Or as a direct screenshot of the database: https://gyazo.com/67abfdc329e1e36aae4e66b0da4b4f75
I would like to avoid this value in the database and instead have it be more readable.
Any tips or suggestions?
The 7889400000 is a UNIX timestamp, indicating a number of milliseconds since the epic. While you can store a value indicating the same moment in a different format, you'll want to make sure that the format you use still allows you to query the value.
A common format that is both readable and queryable it ISO-8859-1, and my current time in that format would be 2022-03-22 06:50:48.
I noticed after re-reading your question that your timeAfterWhichUserIsDeleted is actually an interval and not a moment. If the interval is always going to be in months, you could store countOfMonthsAfterWhichUserIsDeleted: 3 as a more readable form of the same intent. Just note that 3 is equally magic as 7889400000 and the main difference is that I've named the field more meaningfully.

Why is 100 in front of 11 in firebase documents order?

I'm building an app that will display a list of user info, with each one a numeric ID that is stored when creating the profile and used as the docID in firebase. To facilitate the search, I used this method so the ID would be displayed in ascending order. But, after some tests, I notice that, for example, 100 comes first then 11. Why does it happen? Is there a way to correct/prevent it?
I was storing ID as String. But, as the answer suggested, I changed it to both int and double. Still, 11 comes after 100
It's hard to say for certain without seeing your database, but most likely you're storing the numbers as strings. In such cases Firebase (both Firestore and Realtime Database) will sort the values lexicographically, and in that order "100" comes before "11" - just as "baa" comes before "bb".
Why is 100 in front of 11 in firebase documents order?
Because you're sorting alphabetically instead of numerically. 0 comes before 1 in most character encodings like ASCII and Unicode.
After the answers I got and some research I finally got it.
The main problem was that I was storing the ID as String.
After fixing it, I added .orderBy('id') in the place where I retrieve the
uses' list.
Thank you everyone one for the time spent trying to help me.
Another way is to perform sorting after you queried. It is not efficient though, but in case you cannot change the data type or ids themselves:
const query = await db.collection("my-collection").get();
query.docs.sort((doc1, doc2) => parseInt(doc1.id) - parseInt(doc2.id));

Firebase: If a value includes a specific text in database [duplicate]

This question already has answers here:
How to perform sql "LIKE" operation on firebase?
(5 answers)
Closed 3 years ago.
I try to filter the list for items that contain a certain text.
database:
{"123":{"cities":"sss"},"445":{"cities":"hello hi dd"}}
And I want to get the items that contains "hi" within the cities value:
{"445":{"cities":"hello hi dd"}}
I tryd this:
https://xxxxx.firebaseio.com/allitems.json?orderBy="cities"&startAt="hi"
But it's not working... It only shows the items that starts with "hi"...
thanks.
At the time of writing, there is no built-in full-text search capability in the Firebase Realtime Database.
The official Cloud Functions samples include an example of full-text search with the Algolia hosted search service.
Note that there is a workaround if you search for a string that starts with some specific characters (which is different than a string which contains some specific characters).
Have a look at the "Range Queries" section of the REST API documentation:
We can combine startAt and endAt to limit both ends of our query. The
following example finds all dinosaurs whose name starts with the
letter "b":
curl
'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="b"&endAt="b\uf8ff"&print=pretty'
The \uf8ff character used in the query above is a very high code point
in the Unicode range. Because it is after most regular characters in
Unicode, the query matches all values that start with a b.
So in your case you would do as follows:
https://xxxxx.firebaseio.com/allitems.json?orderBy="cities"&startAt="hi"&endAt="hi\uf8ff"

Firebase database: how can I change value of list item?

I have such structure in my database:
User 1
+- items
+- 1
| |- question: some question
| |- answer: some answer
|
+- 2
|- question: another question
I want to add answer to second item, but I don't have the id.
I'm trying to get items and it returns
[null, {answer: some answer, question: some question}, {question: another question}]
But I can't get needed item without answer field and I can't get their ids.
I tried to use equalTo, but it didn't help.
// attempt 1
Query child = _databaseReference.child(item._user).child(db_items).equalTo(null, key: db_answer);
child.reference().once().then((DataSnapshot snapshot) {
print('snapshot: ${snapshot.value}');
});
// attempt 2
Query child = _databaseReference.child(item._user).child(db_items).equalTo(null, key: db_answer);
child.reference().child(db_question).once().then((DataSnapshot snapshot) {
print('snapshot: ${snapshot.value}');
});
First attempt returns the same output as I wrote above, second returns null
So, does anybody know how can I add answer field to second question?
P.S. I use Flutter, but I don't think it means a lot for this issue.
So basically you are trying to add 'answer' to your second item.
I would have done it in this way:
First is to know the key beforehand, so that I can insert a child node in the second item. That way i can write something like:
myDBReference.child("items").child("key_known_beforehand").child("answer").setValue("this is the ansewr");
Or in case I didnt know the key, which seems like the problem here:
I would use Firebase Query. Something like..
myDBReference.child("items").orderByValue().startAt(starting_point_of_child_item).endAt(ending_point_of_child_item).child
This query would givve me the requred node and i would set value there.
"
Using startAt(), endAt(), and equalTo() allows you to choose arbitrary starting and ending points for your queries
To filter data, you can combine any of the limit or range methods with an order-by method when constructing a query.
Unlike the order-by methods, you can combine multiple limit or range functions. For example, you can combine the startAt() and endAt() methods to limit the results to a specified range of values.
"

Firebase "like" search on string [duplicate]

This question already has answers here:
How to perform sql "LIKE" operation on firebase?
(5 answers)
Closed 5 years ago.
I am trying to search the user on the basis of name . It search perfectly if the name is given from first name but didn't search on the string the second name. Where first and second both are saved in one value separated by space for example
"John Smith". If search on "john" or "jo" etc it retrieve the record but if its smith it retrieve nothing.
Code
var ref = firebase.database().ref().child('User').orderByChild("name").startAt(searchString).endAt(searchString + "\uf8ff");
$scope.usercollection = $firebaseArray(ref);
With your query it is normal that you only get results starting with j, jo, joh, john, etc... The startAt method "creates a Query with the specified starting point". So it looks at how your searchString variable starts.
There is no full text search mechanism in Firebse for the moment. You will find on the web several possibilities to implement such a mechanism, e.g.:
https://firebase.googleblog.com/2014/01/queries-part-2-advanced-searches-with.html
https://github.com/FirebaseExtended/flashlight

Resources