Firestore composite Indexing not working: The query requires an index - firebase

UserCollection/{id}/PlayerCollection/{id}
In the last document, there are number of fields
active: true or false
dateInMillies : 123456789
return _firestore
.collection('UserCollection')
.document(userID)
.collection("PlayerCollection")
.orderBy('dateInMillis', descending: true)
.where('active', isEqualTo: true)
.snapshots();
this block of code through an exception:
failed: Status{code=FAILED_PRECONDITION, description=The query requires an index. You can create it here: link to fix it
but the link is broken, so i must do it manually!
so, i went to indexes tab, and created a new composite index
collectionID : PlayerCollection
Fields Indexed: dateInMillis : Descending , active : Ascending
but also didn`t work!

I have an alternative answer.
Make sure when you open the link that you don't include any random characters at the end. I opened the link from vscode's terminal, and it actually had three links that were available to open, but two of them had a trailing comma, which opened a white screen in the Firebase console.

The problem is solved D:
I contacted Firebase support about the broken URL and here is the solution:
It seems that you might have another account linked on your browser.
Probably gmail, if that is the case, please verify that your current
session corresponds with the selected project, or simply try logout /
login with the account that owns the project. You can also try it from
an incognito window
And the generated link solved my issue.

In my case,
I found that the fields indexed should be exactly the same in the query, no more, no less.
If you want to make a new query with different fields (but still in the same collection), you can create new composite indexing with the same collection name.
I hope this will solve the problem.

Related

Is there a way with Hasura to do a mutation based on the result of a query, within the same GraphQL call (Hasura transaction)?

I tried to search for an example but, I presume it's not doable. I am looking to hopefully be proven wrong or to find an official confirmation that it's not doable.
Before using Hasura, I was doing transactional SQL queries that ensured that data was kept consistent.
For example, I would like to create a password reset token if a user requests it, only if the user can be found using an email address. Right now, I have to do 2 queries:
Try to find a user with the specified email address
Insert and assign the token to this user id
In that case, it's not too bad, but now if I want to consume that token, I have to do 3 queries:
Find the valid token
Change the password to the user associated with that token
Delete the token
Obviously, if something goes wrong and the token is not deleted, this could be an issue - so I would be curious to see if there would be ways to merge these queries/mutations into transactions.
Sounds like supporting nested updates would solve this problem for you with the least amount of effort. We are working on a rfc for the feature and hope to start development soon. Please follow this Github issue on our community for future updates.
https://github.com/hasura/graphql-engine/issues/1573
This comment outlines the current scope of the proposed feature. The rfc will provide a more complete explanation.
https://github.com/hasura/graphql-engine/issues/1573#issuecomment-1338057350
You can apply changes to rows that you filter by certain criteria. Here is a sample mutation:
mutation PasswordUpdate($id: uuid!, $token: String!, $new_password: String!) {
update_user(
where: {id: {_eq: $id}, token: {_eq: $token}}
_set: {token: null, password: $new_password}
) {
affected_rows
}
}
That query deletes the token and sets a password for all users (hopefully just one) that have the token assigned.
After some research here is what I found:
For the first example:
Try to find a user with the specified email address
Insert and assign the token to this user id
There are no solutions for this today and as answered by #damel, there is an ongoing RFC to support nested mutations: https://github.com/hasura/graphql-engine/issues/1573#issuecomment-1338057350
Hopefully, this feature will be out soon, but in the meantime, for most cases, it's not such a big deal to have multiple queries as it is possible to catch errors on the first query.
For the second example:
Find the valid token
Change the password to the user associated with that token
Delete the token
When sending multiple mutations in the same query, Hasura treats them as a transaction as announced in 2020.
Of course, it would be nice to do this in the same query (similar to the first example) but since there is a transaction on the mutation, for this case it's still not a problem.
I am sure there are probably cases where this can become a problem but I am not exposed to them right now. Nevertheless, it would be great if the RFC makes it to production, giving more options to Hasura users.

How to paginate data in Firebase in Next.js SSR app?

I am trying to build a next.js server-side rendered blog. For it, I need to paginate the posts data. However, I am yet to find a way to use the query cursors firebase provides to paginate the data. The building query code is:
let postsQuery = firebase.firestore().collection('/posts').orderBy('postedOn', 'asc').limitToLast(10);
if (currentTagFilter !== 'All') {
postsQuery = postsQuery.where('tag', '==', currentTagFilter);
}
Now, this works for the first page, but I do not know how to request the next 10 posts. I could have saved the first document of the query and use .endBefore(firstPost). But, if I create some state in _app.js and save the first document in an array, for example, I cannot find how to make it accessible in getServerSideProps. Not to mention, if the user goes straight to /page/2, nothing will be displayed to him as the query for page 1 has not been performed yet.
How can I paginate the data correctly?
You might want to rethink you pagination strategy entirely. Firestore doesn't support pagination by index or page number. You have to provide a document snapshot or document details from the last seen document in order to get the next page.
Given these limitations and requirements, it's not possible for the user to go straight to page 2 (or any page other than the first one). So, it would be a bad idea to provide a link or mechanism to do that.
If you want to paginate data "correctly" with Firestore, you have to start at the first page, and cycle through the results using startAfter(), providing the details of the document where the last page ended. This is illustrated in the documentation.

Firebase Storage : Get the token of the URL

I currently have an application that works with Firebase.
I repeatedly load profile pictures. However the link is quite long, it consumes a certain amount of data. To reduce this load, I would like to put the link in raw and only load the token that is added to the link.
To explain, a link looks like this: “https://firebasestorage.googleapis.com/v0/b/fir-development.appspot.com/o/9pGveKDGphYVNTzRE5U3KTpSdpl2?alt=media&token=f408c3be-07d2-4ec2-bad7-acafedf59708”
So I would like to put in gross: https://firebasestorage.googleapis.com/v0/b/fir-developpement.appspot.com/o/
In continuation: “9pGveKDGphYVNTzRE5U3KTpSdpl2” which is the UID of the user that I recover already and the or my problem this poses: “alt = media & token = f408c3be-07d2-4ec2-bad7-acafedf59708” which adds randomly for each photo .
I would like to get back only this last random piece …
Is it possible ?
Thank you
UP : 01/11 Still no solution
It's not supported to break apart and reassemble download URLs. You should be treating these strings as if their implementation details might change without warning.

Updating Meteor.users

I've created a form for users to update their profiles. When I submit the form I'm receiving a [403] error.
Not permitted. Untrusted code may only update documents by ID.
My question is, if I'm going to use Meteor.users.allow, where - in what file/directory - do I write this code?
Thanks,
Nathan
The error you're getting is not a result of your allow/deny rules. You would get a straight 'Access Denied' error if it were.
When updating your users (as well as having the correct allow rules in place) you need to update your user by their _id- especially if they are being updated on the client end.
So instead of
Meteor.users.update({name: "etc"}, {$set:..});
You need to split it in two, one to get the _id and then one to update your document on that.
var user = Meteor.users.findOne({name: 'etc'});
Meteor.users.update({_id: user._id}, {$set:..});
The rule is on the client you can only use _id to find the document when updating.

Why does the url property key in Firebase snapshot keep changing?

I have not seen any discussion or awareness so far that Firebase does in fact make available a unique identifier--in fact the full URL--to each specific data record via their "snapshot" which they return, i.e. the wrapper around the data record (accessed via snapshot.val()). By doing a basic property examination of the snapshot I discovered that the unique URL is available (see examples below). However, it seems that, for some reason, Firebase keeps changing the name of the key every few days, causing my application to break. I have to go in and re-discover the new URL property key and change it so that it will work again.
Here are three examples of how I have seen the key change so far. Each value is the same, but the key keeps changing over time (i.e.: "Wb", "Xb", "bc").:
getMemberBySnapshot - snapshot has prop Wb with value https://prototype1.firebaseio.com/users/-IwohKfw1l5F3gFqyJJ5
getMemberBySnapshot - snapshot has prop Xb with value https://prototype1.firebaseio.com/users/-IwohKfw1l5F3gFqyJJ5
getMemberBySnapshot - snapshot has prop bc with value https://prototype1.firebaseio.com/users/-IwohKfw1l5F3gFqyJJ5
I have read Firebase's suggestions that developers should use an email address if they want a unique key (what if my model does not use an email field? What if a user wants to change their email?), or Firebase suggests altenatively to retrieve all existing records and then search through them on the client. Neither of these solutions are satisfying. But I'm seeing that they do provide the unique URL to each data record in the 'snapshot'. Why do they not provide a stabilized key so that a developer can call it consistently???
Firebase.js is a compiled script. The names of internal variables will change every time we compile it and release a new version, so you should definitely not be relying on any properties that are not documented on our website.
For your specific case, you should be using:
snapshot.ref().toString()
in order to get the URL.

Resources