I am writing a language dictionary using Flutter with Firestore. I have database named ‘Spanish’ and 2 documents ‘easy’ and ‘difficult’. Each document is a set pairs - a key is original Spanish word and the value is translation of this word.
I want to find which keys (original Spanish words) appears in both ‘easy’ and ‘difficult’ documents. My query (which is not working) is:
var myResult = await FirebaseFirestore.instance
.collection('Spanish')
.doc('easy')
.get()
.then((snapshot) {
if (snapshot != null) {
snapshot.data()?.forEach((key, value) {
var myData2 = **checkIfSelected**(key);
print(myData2) ;
});
Future<dynamic> checkIfSelected(String key) async {
bool ifSelected = false;
var myResult2 = await FirebaseFirestore.instance
.collection('Spanish')
.doc('difficult')
.get()
.then((snapshot) {
if (snapshot != null) {
snapshot.data()?.forEach((k, v) {
if (k == key) {
ifSelected = true;
}
}
});
return ifSelected;
}
Why is not working? I made a lot of displays which I removed from quoted code, but function checkIfSelected returns Instance of 'Future' instead of bool. This is async function with await, so as I understand it should not return Futures. I tried make a change:
var myData2 = await checkIfSelected(key);
but got error:
The await expression can only be used in an async function. Try marking the function body with either 'async' or 'async*'.dart(await_in_wrong_context)
But checkIfSelected
is already an async
function.
Any ideas what I did wrong in my code, or maybe there is another approach to this problem?
CodePudding user response:
Try This way,
void getData() async {
var snapshot = await FirebaseFirestore.instance.collection('Spanish').doc('easy').get();
var data = snapshot.data();
for (var key in (data?.keys.toList() ?? [])) {
var myData2 = await checkIfSelected(key);
print(myData2);
}
}
Future<bool> checkIfSelected(String key) async {
var snapshot = await FirebaseFirestore.instance.collection('Spanish').doc('difficult').get();
var data = snapshot.data();
for (var k in (data?.keys.toList() ?? [])) {
return k == key;
}
return false;
}
Note:
Asynchronous calls don't work with .forEach(), you need to use traditional loops. Why? This article explains it very well. I just discovered that Dart and Node.JS are almost the same.
CodePudding user response:
I write another approach to get the words that occur in both easy and hard documents:
Future<Map<String, dynamic>> getEasy() async {
DocumentSnapshot myResult = await FirebaseFirestore.instance
.collection('Spanish')
.doc('easy')
.get();
return myResult.data() as Map<String, dynamic>;
}
Future<Map<String, dynamic>> getDifficult() async {
DocumentSnapshot myResult = await FirebaseFirestore.instance
.collection('Spanish')
.doc('difficult')
.get();
return myResult.data() as Map<String, dynamic>;
}
Future<List<String>> getOccurrences() async {
List<String> spanishWordsThatOccursOnBoth = [];
Map<String, dynamic> easy = await getEasy();
Map<String, dynamic> difficult= await getDifficult();
easy.forEach((key, value) {
if (difficult.containsKey(key)) {
spanishWordsThatOccursOnBoth.add(key);
}
});
return spanishWordsThatOccursOnBoth;
}
you can call it like this, and it will search for them and return a list with those Spanish words:
List<String> OcurrencesSpanishWords = await getOccurrences();
CodePudding user response:
If you want to use async
/await
you should not use then
.
With just the former, it'd be:
Future<dynamic> checkIfSelected(String key) async {
bool ifSelected = false;
var snapshot = await FirebaseFirestore.instance
.collection('Spanish')
.doc('difficult')
.get()
if (snapshot != null) {
snapshot.data()?.forEach((k, v) {
if (k == key) {
ifSelected = true;
}
}
return ifSelected;
}