Firebase | Problem with collectionGroup query - google-cloud-firestore

I'm trying to use a collectionGroup query to fetch the data from a specified farm, using firebase-functions. Here's my code:
app.get('/api/intervals/:farm_id', async (req, res) => {
const farmId = req.params.farm_id;
try {
const querySnapshot = await db
.collectionGroup('farms')
.where("id", "==", farmId)
.get();
const farmData = [];
querySnapshot.forEach((doc) => {
farmData.push(doc.data());
console.log(doc.id, ' => ', doc.data());
});
return res.status(200).send(farmData);
} catch (error) {
console.log(error);
return res.status(500).send(error);
}
});
There is definitely a farm in the database with the supplied code. For example, if I change the code in try to the below, I get the data as expected:
const farmRef = db
.collection('accounts')
.doc('lz8V32bjQGa9x1oecUu9')
.collection('farms')
.doc(farmId);
let farm = await farmRef.get();
let farmData = farm.data();
return res.status(200).send(farmData);
But I want to use a collectionGroup so I don't have to specify the parent account ID also.
What am I doing wrong here? Thanks in advance!

According to my understanding this is related with the fact that in your working code you are assigning directly from DocumentSnapshot, while in example in of the issue you are iterating over QuerySnapshot returned by get from query.
In documentation we can find that documents in QuerySnapshot are in array property docs.
So I think you should change forEach loop accordingly:
querySnapshot.docs.forEach((doc) => {
farmData.push(doc.data());
console.log(doc.id, ' => ', doc.data());
});

I have worked out that the problem was that my code was looking for a field named id. My query works if I manually add a field called ID as highlighted below:

Related

Flutter FireStore: The method 'where' isn't defined for the type 'DocumentReference'

If I use the code, I can receive the data correctly.
However, using .where, I get the error:
The method 'where' isn't defined for the type 'DocumentReference'.
Try correcting the name to the name of an existing method, or defining a method named 'where'.
code:
chamaBancoDeDados(curso, materia, id, dificuldade) {
Map<String, dynamic> dados = {};
final documentoRef = FirebaseFirestore.instance
.collection('cursos')
.doc(curso)
.collection(materia)
.doc(id)
.where('dificuldade', arrayContainsAny: ['normal']);
documentoRef
.get()
.then((DocumentSnapshot documento) {
if (documento.exists) {
try {
dados = documento.data() as Map<String, dynamic>;
print("dados são: $dados");
} on StateError catch (e) {
print('Erro tentando adquirir o documento no banco de dados: $e');
}
} else {
print('O documento não existe no banco de dados');
}
});
return dados;
}
}
I've already searched a lot on the internet, including the Firebase documentation, but I don't know where I'm going wrong.
Your current code tries to read a single document with a known ID, in which case there is no way to further filter the data with a where clause. So if you only want to read that single document, remove the where:
final documentoRef = FirebaseFirestore.instance
.collection('cursos')
.doc(curso)
.collection(materia)
.doc(id);
If on the other hand, you want to read all documents from the cursos collection with a normal difficulty level, that be done by removing the .doc(id) clause:
final documentoRef = FirebaseFirestore.instance
.collection('cursos')
.doc(curso)
.collection(materia)
.where('dificuldade', arrayContainsAny: ['normal']);
If you see in line 7 of your code, that gets a document from firestore, and you cant use .where() on a document.
.where() is used for collections to check the condition for all documents (in that collection) and return the documents which satisfy the need.
From the above given info, I'd suggest you to remove 7th line of code and try again.
Please share your Firestore hierarchy so that we could suggest a better way to perform your queries.
I make this and works how I wanted:
final teste = FirebaseFirestore.instance
.collection('cursos')
.doc(curso)
.collection(materia)
.where('dificuldade', arrayContainsAny: [dificuldade]);
await teste
.get()
.then((event) {
print("${doc.id} => ${doc.data()}");
}
}, onError: (e) => print("Error completing: $e"));

Perform simple queries in Cloud Firestore - how can i filter all through select?

I need to to filter data through queries from Firestore, but how can I also get all of them(in my case all states in firestore)? What should be useState value in this case? I'm a newbie :) Thank you for your help, I really appreciate it.
//WHAT useState VALUE SHOULD I USE TO GET ALL STATES IN DATABASE?
const (city, setCity) = useState("CA");
const citiesRef = collection(db, "cities");
const q = query(citiesRef, where("state", "==", city));
Tried to search in firestore docs and google.
you need to use getDocs() method provided by firebase as follows
here, q is your query ( const q = query(collection(db, "cities"), where(....));
add following code -
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data())
});
you can refer to this link
As you wanted to use useState, You can pass an empty string ” “ or Null value and use != instead of = operator in the where clause.
And use getDocs() to retrieve all documents as mentioned by #Prathmesh
Here is the complete code:
const (city, setCity) = useState(" ");
const citiesRef = collection(db, "cities");
const q = query(citiesRef, where("state", "!=", city));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});

flutter firestore: how to get a query of documents

Im trying to get a list of user objects from firestore through a query. My current attempt looks like this:
List<User> getDiscoveryUsers(
String userId,
) async {
Query<Object?> query =
userCollection.where('finishedOnboarding', isEqualTo: true).limit(10);
var collection = await query.get();
//get the users list from query snapshot
var users = collection.docs.map((doc) => User.fromSnapshot(doc)).toList();
return users;
}
However I am getting the error:
Functions marked 'async' must have a return type assignable to 'Future'.
Try fixing the return type of the function, or removing the modifier 'async' from the function body.
I know there are a few similar questions on stack overflow, but i just cant seem to get this to work. Anyone know whats going on?
Thanks!
Just change the return type of your function from List<User> to Future<List<User>>.
Happy coding:)
your return type should be Future and must wait with await when running query on firestore.
Future<List<User>> getDiscoveryUsers(
String userId,
) async {
Query<Object?> query =
userCollection.where('finishedOnboarding', isEqualTo: true).limit(10);
var collection = await query.get();
//get the users list from query snapshot
var users = collection.docs.map((doc) => User.fromSnapshot(doc)).toList();
return users;
}

Get all documents from a Firestore collection in Flutter

I tried with different ways but i can't edit the structure of code
//First way
QuerySnapshot querySnapshot = await db.firestoreInstance.collection('user-history').get();
var list = querySnapshot.docs;
print('MY LIST ===== $list');
//Second way
final CollectionReference collectionRef = db.firestoreInstance
.collection(historyCollection);
print('MY SECOND LIST ===== $list');
collectionRef.get().then((qs) {
qs.docs.forEach((element) {
print('MY doc id ${element.id}');
});
});
In my firebase collection(historyCollection) i have four documents but the debugger returns me empty array []. Is there another way to call all documents in certain collection through flutter?
I'm trying to call this method through FutureBuilder component.
My version of firestore is: "cloud_firestore: ^0.16.0+1"
This should do the trick:
Future<List<dynamic>> getCollection(CollectionReference collection) async {
try {
QuerySnapshot snapshot = await collection.get();
List<dynamic> result = snapshot.docs.map((doc) => doc.data()).toList();
return result;
} catch (error) {
print(error);
return null;
}
}
The entire problem was not from these fragments of code. This problem is came out from this that my collections have subcollections. I read about this and i understand that subcollections can live without their ancestors and the only way to access parents is to do this is directly specify the exact path and name of the document. To work this code in my case was needed to add dummy components of my entire set of collections. For more information please look up these two topics:
-> https://firebase.google.com/docs/firestore/using-console
-> Firestore DB - documents shown in italics

Elegant way to dynamically query firestore [duplicate]

I have fetch some data from firestore but in my query I want to add a conditional where clause. I am using async-await for api and not sure how to add a consitional where clause.
Here is my function
export async function getMyPosts (type) {
await api
var myPosts = []
const posts = await api.firestore().collection('posts').where('status', '==', 'published')
.get()
.then(snapshot => {
snapshot.forEach(doc => {
console.log(doc.data())
})
})
.catch(catchError)
}
In my main function I am getting a param called 'type'. Based on the value of that param I want to add another qhere clause to the above query. For example, if type = 'nocomments', then I want to add a where clause .where('commentCount', '==', 0), otherwise if type = 'nocategories', then the where clause will be querying another property like .where('tags', '==', 'none')
I am unable to understand how to add this conditional where clause.
NOTE: in firestore you add multiple conditions by just appending your where clauses like - .where("state", "==", "CA").where("population", ">", 1000000) and so on.
Add the where clause to the query only when needed:
export async function getMyPosts (type) {
await api
var myPosts = []
var query = api.firestore().collection('posts')
if (your_condition_is_true) { // you decide
query = query.where('status', '==', 'published')
}
const questions = await query.get()
.then(snapshot => {
snapshot.forEach(doc => {
console.log(doc.data())
})
})
.catch(catchError)
}
For the frontend Web SDK:
Or you can look at this link for a different method:
Firestore conditional where clause using Modular SDK v9
let showPublishStatus: boolean = true
let conditionalConstraint: QueryConstraint = showPublishStatus
? where("status", "==", "published")
: where("status", "!=", "published")
let queryWebSDK = query(collection(db, "Collection"), conditionalConstraint)