[🐛] New modular API for `FieldPath` no longer has `documentId()` (resolution: it does not exist anymore in firebase-js-sdk, use other methods)
Issue
The new modular API doesn't seem to have the static documentId() from FieldPath. This field is used to query based on document ID. The Namespaces API has it, but not the modular so it is breaking compatibility.
Or am I missing something?
Project Files
N/A
Javascript
Click To Expand
package.json:
# N/A
firebase.json for react-native-firebase v6:
# N/A
iOS
Click To Expand
ios/Podfile:
- [ ] I'm not using Pods
- [x] I'm using Pods and my Podfile looks like:
# N/A
AppDelegate.m:
// N/A
Android
Click To Expand
Have you converted to AndroidX?
- [ ] my application is an AndroidX application?
- [ ] I am using
android/gradle.settingsjetifier=truefor Android compatibility? - [ ] I am using the NPM package
jetifierfor react-native compatibility?
android/build.gradle:
// N/A
android/app/build.gradle:
// N/A
android/settings.gradle:
// N/A
MainApplication.java:
// N/A
AndroidManifest.xml:
<!-- N/A -->
Environment
Click To Expand
react-native info output:
N/A
-
Platform that you're experiencing the issue on:
- [ ] iOS
- [ ] Android
- [ ] iOS but have not tested behavior on Android
- [ ] Android but have not tested behavior on iOS
- [ ] Both
-
react-native-firebaseversion you're using that has this issue:-
e.g. 5.4.3
-
-
Firebasemodule(s) you're using that has the issue:-
e.g. Instance ID
-
-
Are you using
TypeScript?-
Y/N&VERSION
-
- 👉 Check out
React Native FirebaseandInvertaseon Twitter for updates on the library.
I don't see it on the upstream firebase-js-sdk API? https://firebase.google.com/docs/reference/js/firestore_.fieldpath
Can you point to a reference doc for the firebase-js-sdk modular API that has it, I may be looking at the wrong thing - but it seems like if that one was on namespaced but not modular that perhaps it moved or was present in another (preferred) location and you need to port this specific code to use the other spot
I do see it on the old API https://firebase.google.com/docs/reference/js/v8/firebase.firestore.FieldPath
Perhaps it is because it is clearer to simply specify the document and do a get (or ==) vs using that, it was simply removed? It appears to just be removed -- see https://stackoverflow.com/a/62562787/9910298 for this idea
Hmmm. You might be right. I can see this function on the node API and namespaced API for sure but not the modular API. Not sure if they never included it or there is a technical reason for not having it in the modular API, but either way unless they add it there, to stay consistent we can't have it here either.
Although I don't think I agree much with the reasoning in the stackoverflow post. For my project I use the documentId() in snapshot query to sort based on some timestamp and then by documentId. So, just relying on .get() is not enough. For now, I'm going to just use __name__ which works, but that's something internal I'm using it and probably brittle. :(
Thanks for looking into this. Feel free to close this issue if no further action is warranted.
Cheers.
I think documentId is missing in types and it has other purposes other than just accessing a doc by id for example
query(usersColRef(), where(FieldPath.documentId(), "in", userIds));
how else we could achieve this query ?
And I believe the function exists it's just missing in the types
@aazarkhish if it is missing in firebase-js-sdk it will be missing here, we follow them. If this is something the modular API needs for FieldPath, you should open an issue with firebase-js-sdk, and if they make this change then you can open a feature request here for us to follow them. We need to follow their API though, we are designed to be a drop-in replacement for them with our only deviations being things that are truly platform differences (like, we have some modules they don't and some APIs they don't because we have platform API access, but this is not one of those differences)
Thanks @mikehardy
But I believe firebase-js-sd has that in their types
https://github.com/firebase/firebase-js-sdk/blob/feb2c9dfa29c9dff01c1272e56f6258176dc6b3a/packages/firestore-types/index.d.ts#L494
But it is missing in modular types in this repo
https://github.com/invertase/react-native-firebase/blob/e6642ec51e7e7771611c1c7e36aa6bdeeb4989c9/packages/firestore/lib/modular/FieldPath.d.ts#L9
@aazarkhish 🤔 and yet, in their docs it does not exist? https://firebase.google.com/docs/reference/js/firestore_.fieldpath Does it actually work on firebase-js-sdk using their modular APIs if you attempt it ? I haven't tried personally - been quite busy with other stuff and haven't been able to do concrete testing, apologies.
No Problems @mikehardy It actually works in @react-native-firebase v21.12.0 it's just missing in types , I have to brute force the type
import {
query,
FieldPath,
where
} from "@react-native-firebase/firestore";
query(usersColRef(), where((FieldPath as any).documentId(), "in", userIds));
Yes but does it work in firebase-js-sdk - that's our template
While migrating a project to version 21.12.0 I was encountering this issue: still there's no static property like this on the type working nor there's any workaround apart from casting FieldPath as any.
@andrastoth-ws
Yes but does it work in firebase-js-sdk - that's our template
@mikehardy
The minimal reproduction:
import { FieldPath } from '@react-native-firebase/firestore'; // version 21.12.0
console.log('!!!! HELLO', (FieldPath as any).documentId());
Logs:
Android Bundled 8292ms index.js (3393 modules)
LOG !!!! HELLO {"_segments": ["__name__"]}
Does this answer the question?
@andrastoth-ws
Does this answer the question?
Nope, the question is:
Yes but does it work in firebase-js-sdk - that's our template
Your reproduction is for react-native-firebase. I need to know if this works for firebase-js-sdk or not. If it works there then it is a feature gap here and we should close it.
If it does not work here we will not make it work here, as our template for APIs and functionality is firebase-js-sdk in nearly all matters
Your reproduction is for react-native-firebase. I need to know if this works for firebase-js-sdk or not. If it works there then it is a feature gap here and we should close it.
Alright, the result was what you suspected (using the package "firebase": "^10.x"):
import { FieldPath } from 'firebase/firestore';
console.log('documentId on FieldPath', (FieldPath as any).documentId());
> ERROR
> [...] FieldPath.documentId is not a function
So this means that while the type is correct, react-native-firebase has an extra functionality.
The question is that I can't seem to find answer in the quite thin documentation of Firebase (not to mention the migration guide): what's the alternative?
If you really need this (at least until upstream adds this), you can use '__name__' string instead of FieldPath.documentId() when building the query. ugly and dangerous but it works. That's what I'm doing.
If you really need this [...]
Update Now that I understood the code a bit better I have found what was the intention.
- let's say we have a simple collection of objects
- the objects all have document IDs but they themselves has no IDs
- now if you have a bunch of document IDs you need to fetch and you were to query this, this is how it would look like in the modular API
import { collection, query, where, documentId, getDocs } from 'firebase/firestore';
const collectionRef = collection(firestore, 'my-collection');
const docIdInListQuery = query(collectionRef, where(documentId(), 'in', ['x ID', 'y ID', 'z ID']));
const querySnapshot = await getDocs(docIdInListQuery);
So it seems that this top-level documentId() function is missing from @react-native-firebase/firestore.
(My old comment for historic reference) The thing is I don't know, I'm migrating an inherited codebase. It seems others use this and this was a thing in the 2022s 🙂. It's my fault that I haven't fully understood the need for it.
For example in our case we have some generated conditions - I am not sure it is a good pattern at all. Probably it is not and that's why FieldPath.documentId() got removed.
someIds.map((id) => [
{
field: FieldPath.documentId(),
operation: 'in',
value: id,
}
];
I strongly encourage you to post up your use case on stackoverflow tagged up really well with firebase tags - do your best on the question - the firebase team offers official support there and I've seen them give great answers to people that solve their use case with the APIs available
I'm sorry this feature isn't going to be there in the modular API - it was in the namespaced, it wasn't extra there - but without a corresponding API on firebase-js-sdk it's not going to come over to modular unfortunately
I really appreciate you running the test though - forgot to say - I was honestly curious. I was pretty sure I'd analyzed the types correctly but that's different from actually running the experiment. I appreciate you tested it and now we know for sure
The problem seems to be purely with TS definitions, so I just did this in my global.d.ts file. everything works and is presensed by IDE
import {
FieldPath as OGFieldPath,
FirebaseFirestoreTypes,
} from '@react-native-firebase/firestore'
declare module '@react-native-firebase/firestore' {
// firebase is poorly typed and documentId() exists in implementation but not in d.ts definition
export declare class FieldPath extends OGFieldPath {
static documentId(): FirebaseFirestoreTypes.FieldPath
}
}
@diadiushko I strongly suggest you read the comments above. The problem is not the TS definitions. The problem is the method is gone in the modular namespace. It doesn't exist anymore. That it exists, for now, temporarily, in a way that you can workaround with type hacking, is not a solution. It's you accessing an old namespaced method that no longer exists and is only there because we are in the middle of a conversion.
Your comment "firebase is poorly typed" should be re-written as "I don't want to fully migrate to the modular API so I'm going to directly access a legacy method via a type workaround"
@mikehardy I was only replying to this comment, suggesting more ts-ish solution to approach the types for now. Something must've happen to the comment referencing. It's not at all the solution to the problem, since the method can become absent at any time.
Update: @mikehardy I've found it in firebase/firestore version 10.3.1 in the type definition:
// source: @firebase/firestore/dist/index.d.ts
/**
* Returns a special sentinel `FieldPath` to refer to the ID of a document.
* It can be used in queries to sort or filter by the document ID.
*/
export declare function documentId(): FieldPath;
So while it seems that FieldPath no longer has a static member, the documentId() function has been moved up to the root level.
Also this same documentId() is not available in @react-native-firebase/firestore.
Since my question I've figured out the code and boiled down the excess to a simple query. I've updated my comment with that. https://github.com/invertase/react-native-firebase/issues/8356#issuecomment-2759146075
@andrastoth-ws very interesting. I looked into this again and you're right. I couldn't figure out how a documentId() function could be valid without the internal context of the document or FieldPath it was related to until I read the implementation:
https://github.com/firebase/firebase-js-sdk/blob/88a8055808bdbd1c75011a94d11062460027d931/packages/firestore/src/lite-api/field_path.ts#L67-L73
/**
* Returns a special sentinel `FieldPath` to refer to the ID of a document.
* It can be used in queries to sort or filter by the document ID.
*/
export function documentId(): FieldPath {
return new FieldPath(DOCUMENT_KEY_NAME);
}
...and
https://github.com/firebase/firebase-js-sdk/blob/88a8055808bdbd1c75011a94d11062460027d931/packages/firestore/src/model/path.ts#L24
export const DOCUMENT_KEY_NAME = '__name__';
...so that's how they do it! It really is a "sentinel" / hard-coded value.
I think we can support that.
In the meantime, to verify this works, it appears you can construct the same semi-magical FieldPath right now, in the same way they do (new FieldPath('__name__')) and use that in your queries for where / order by and...it should work? If someone tests that and reports back it works, then we have a path forward here
@mikehardy Sorry for the late reply, I've run into this requirement again and managed to test out new FieldPath('__name__').
The situation was this:
- we have a collection of
{ [docId: string]: boolean } - the query was asking for a subcollection through the document ID
The final code I used that works well now to query this type of object:
const myIds = ['x', 'y', 'z'];
const condition = {
field: new FieldPath('__name__'),
operation: 'in',
value: myIds,
};
So for anyone looking for a quick fix: just use new FieldPath('__name__') it really works.
Thanks for reporting back with success - and glad it works, obviously! - reopening for implementation here
Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?
This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.
I figured out the issue using a combination of google gemini and @andrastoth-ws and @mikehardy 's comments. to quote gemini:
You're running into a known change in the react-native-firebase modular SDK. The documentId() field path has indeed been removed for orderBy, startAt, and endBefore in the modular syntax.
The rationale behind this change is to encourage a more explicit data model. If you need to query or order by a document's ID, the recommended approach in Firestore (and now in react-native-firebase modular) is to store the document's ID as a regular field within the document itself.
While the solutions mentioned above might work, I agree with gemini it makes more sense to add documentId as a field in the payload of the document, and make sure it matches the actual doc id. then you dont need this dynamic functionality, you are just sorting on a typical field value (in my case I was trying to use orderBy(documentId()) )
works for me!
Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?
This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.
Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?
This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.
I don't think this has been fixed, so I'd ask the bot to please reopen it.