I have written Flutter code involving Firebase and Firestore for retrieving data regarding the current user immediately after their signing-in.
My expectation was for Firestore to confirm data within Firestore, but instead Firestore has requested an index.
The problem I have is having no clue on how to produce the index being requested.
The code is as follows:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart' as auth;
import '../widgets/textfield_try.dart';
class LoginScreen extends StatelessWidget {
LoginScreen({super.key, this.onTap});
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
FirebaseFirestore _dB = FirebaseFirestore.instance;
Function()? onTap;
static const source = Source.serverAndCache;
Future<void> signUserIn() async {
await auth.FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text, password: passwordController.text);
if (_auth != null) {
try {
final docRef = await _dB.collectionGroup('signInData').where(
'eAddress', isEqualTo: _auth.currentUser!.email).get().then((
value) {
final userData = value.docs.toList();
print(userData);
});
} on Exception catch (e) {
print(e);
}
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.blue[900],
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(padding: EdgeInsets.only(top: 0, bottom: 37)),
TextField_Try(
hintText: 'Username',
obscureText: false,
controller: emailController),
Padding(padding: EdgeInsets.only(top: 0, bottom: 0)),
Padding(
padding: EdgeInsets.only(
top: 8.0, left: 8.0, right: 8.0, bottom: 28.0),
child: TextField_Try(
hintText: '**************',
obscureText: true,
controller: passwordController,
)),
Padding(padding: EdgeInsets.only(bottom: 10)),
ElevatedButton(onPressed: signUserIn, child: Text('Sign In')),
Padding(padding: EdgeInsets.only(bottom: 25)),
],
),
),
),
),
);
}
}
Flutter’s response to the code is:
D/FirebaseAuth(12349): Notifying id token listeners about user ( ************************ ).
I/flutter (12349): [cloud_firestore/failed-precondition] Operation was rejected because the system is not in a state required for the operation's execution. If performing a query, ensure it has been indexed via the Firebase console.
My question is, how is an index for a collection-group query based on a single collection-id produced?
Thank you for considering my question.
2
Answers
After hearing of the solution posted and saluted here, I noticed another way in which Firestore permits the creation of an index, and in this particular way, Firestore checks the proposed index and offers a link to create it for you automatically:
So, on the Firestore first screen, notice options to create indexes, but also notice the option to build a query (as shown in the photo below)
If you select the Query-builder option you'll be introduced to a menu that automatically incorporates your Firestore's collection and field names (as shown in the photo below)
You can add other features to the query, like the ordering of results (as shown below)
If you run the query that you are proposing and Firestore decides that that query requires an index, then Firestore will offer you a link towards having that index created for you automatically (as seen below)
Okay, so that's everything, and now you know two ways of creating an index for Firestore's collection-group queries ..... Haaaappy coding : )
Since you’re querying
collectionGroup('signInData')
, you’ll need to create an index on that collection group. In your case you need a single-field index on theeAddress
field of thesignInData
collection group.To do this in the Firebase console:
Single field
panel, since you want to add an index on a single field.signInData
in the Collection ID field andeAddress
as the Field path.Finally: click Next and then Save
Here’s an example of such an exemption/index I created for this use-case:
And the Dart/Flutter code that I then used to query this collection group through that index:
I initially tested it with JavaScript code using the modular SDK, so here’s that too: