Query Firebase using Map value, Flutter - android

I'm trying to query to my Firebase collection using the value inside of Array. I'm using arrayContains and then passing the value like shown in the code, but after querying, it returns a length of 0.
FirebaseFirestore.instance
.collection('chatrooms')
.where('users.0', arrayContains: {'studentid':'1WINXTQdshhn4jLfhMWWaZNNdL32'})
.get();
Here's an image of my database.
Database Collection

This cannot be done using array-contains. You must use the entire student object to query using array-containing. This query tries to find {'studentid':'1WINXTQdshhn4jLfhMWWaZNNdL32'} object inside the array of users.0 field.
Read more about this here https://firebase.google.com/docs/firestore/query-data/queries#array_membership.

Related

Firestore Query not ordering data correctly

I have a stream that fetches data from my Firestore database and orders them according to the latest message. The problem is that the stream does not order them correctly. So basically it fetches the data once, and if I add a new message, it is not shown on top. Any idea why?
Here is my query:
The Stream:
Stream<List<RoomsListModel>>? chats;
The query:
#override
void initState() {
chats = FirebaseFirestore.instance
.collection("rooms")
.where("users", arrayContains: userId)
.where("latestMessage", isNull: false)
.orderBy("latestMessage")
.orderBy("latestMessageTime", descending: true)
.snapshots()
.asyncMap((events) =>
Future.wait([for (var event in events.docs) generateRoom(event)]));
super.initState();
}
So apparently in Firestore, you cannot do a conditional query like "isNull" and then orderBy another value.
Yes, you can. If a field in Firestore holds the value of null, null being a supported data type, you can query against it. Besides that, you can also order the results by another field, if and only if you create an index.
Found a solution: So apparently in firestore you cannot do a conditional query like "isNull" and then orderBy another value. Therefore I found a workaround: I just changed the conditional query to where "latestMessageTime" is null and ordered by latest Message time.

Not able to use getRef() of Firebase in android

I need to update the data in Firebase database. I have displayed the data in Recyclerview. I need to get the child reference of the position i click in Recyclerview. An not able to use getRef() there to get the reference.
You need to generate a unique key with
String unique = reference.push().getKey();
when saving data to firebase, then you can use that unique key to modify content of that node later.
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Transactions").child(uniqueId)...
You can show your getRef(position) method in your question, maybe another solution can come from there.

Removing map elements from Google Cloud Firestore

I'm trying to remove a map<> from Google Cloud Firestore.
I use the following code for updating in Firestore
fun updateData(userId: String, values: Map<String, Any>) =
db.collection(COLLECTION_DATA).document(Id).update(values)
The document contains the used id's generated for google sign in and one of the field in the document is a map<Key,Value> . I'm trying to delete the content of the Field (removing a specific <key,value> pair)
I pass (userId, mapOf("FieldName.${Key}" to FieldValue.arrayRemove(Value))) as the parameter while calling the above firestore function.
But after updating the value in Firestore, the key is left out and the values are cleared.
If I pass (userId, mapOf("FieldName" to FieldValue.arrayRemove(Key))) as the parameter, then the whole map<> is removed (which is what I want) but the data structure of the Field is converted as an array after performing the update.
FieldValue.arrayRemove() is for array type fields only. It won't work here, because you're not actually using any arrays or lists.
You will just want to use FieldValue.delete() to remove the any map key and its value.
updateData(userId, mapOf("FieldName.${Key}" to FieldValue.delete()))

How to query documents containing array of objects in Firestore collection using whereArrayContains() filter on Android?

I have a collection in firestore where each document contains an array of contacts and I want to query those documents where any contact's email id is a certain value.
I came across whereArrayContains() filter at https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/Query#whereArrayContains(java.lang.String,%20java.lang.Object), with the following description:-
public Query whereArrayContains (String field, Object value)
Creates and returns a new Query with the additional filter that documents must
contain the specified field, the value must be an array, and that the
array must contain the provided value.
A Query can have only one whereArrayContains() filter.
Can the value in the above method point to a field inside an object for an array of objects?
Also, the phrase the value must be an array is a little confusing given the method parameter is also called value. I am sure the documentation means that the field should be present in the document and its value should be an array and that the array should contain the value parameter.
You cannot query fields of objects in arrays in a Firestore query. The array-contains query will instead compare with the objects in an array.
the value must be an array
This refers to the value of the field you are trying to query against. Better phrasing for this would be
Creates and returns a new Query with the additional filter that documents must contain the specified field, the value of the specified field must be an array, and that the array must contain the provided value.
If you are trying to filter for a user ID or something similar, consider adding a second array to the object you are querying, then adding the IDs as strings to that array:
{
"name": "test",
"users": [someUserObject, someOtherUserObject],
"userIds": ["someId", "someOtherId"]
}
then query that array instead:
someRef.whereArrayContains("userIds", someId);
According to the documentation, the field point to the array and value means the String you want to check is present in array or not.
You can use the array_contains operator to filter based on array
values. For example:
CollectionReference citiesRef = db.collection("cities");
citiesRef.whereArrayContains("regions", "west_coast");
This query returns every city document where the regions field is an
array that contains west_coast. If the array has multiple instances of
the value you query on, the document is included in the results only
once.
The data is added as:-
CollectionReference cities = db.collection("cities");
Map<String, Object> data1 = new HashMap<>();
data1.put("name", "San Francisco");
data1.put("state", "CA");
data1.put("country", "USA");
data1.put("capital", false);
data1.put("population", 860000);
data1.put("regions", Arrays.asList("west_coast", "norcal"));
cities.document("SF").set(data1);
As others have said, it's not possible to do what you ask.
The "Firebase-y" way to do what you want, is to create a sub-collection rather than an array, and then each object in the array is instead a document in the sub collection.
You can then query the individual field in the sub-collection using collection-group queries.
If you need access to the parent document, you'll can access it by calling
snapshot.document.parent.parent
which returns a DocumentReference. (The parent of the document is a collection, so its .parent.parent to get the parent document). You'll then have to re-query for that reference.
Instead of using two arrays like the accepted answer, you can use map instead, structure your data like this:
{
users: {
userId1: {
name: "...",
//rest of the fields
},
userId2: {
name: "...",
//rest of the fields
}
}
//rest of the fields
}
Then use this query to filter by an id
collectionRef.orderBy("users.userId1")

How to get value of some field in firebase firestore android?

Like upper question, i want to get value of some field in firebase firestore instead of all document with DocumentSnapshot
like this in SQL SELECT col_1, col_2, col_3 FROM table_name
How can i do it?
Thank you for the help.
The Cloud Firestore client-side SDKs always read and returns full documents. There is no way to read a subset of the fields in a document.
You can retrieve the entire document, and then process the DocumentSnapshot to just use the fields you're interested. But this means you're using more bandwidth than needed. If this is a regular occurrence for your app, consider creating a secondary collection where each document contains just the fields you're interested in.
Also see Doug's answer here (for Swift): How to access a specific field from Cloud FireStore Firebase in Swift
Firestore can read single field value.
Firebase guides looks like didn't show these simple method.
For example:
[android]
String value = document.getString("col_1");
[node.js]
const value = doc.data().col_1
Firebase allows a few ways to query like an RDBMS database. And these are very handy too. Try the Where clause. It returns a single document but u can add multiple filters.
check for more
try this code:
//set a global variable
dataList: Array<any>;
const dataCollection = firebase.firestore().collection('data');
dataCollection.get(query => {
query.forEach(docs => {
this.dataList.push({id: doc.id, data:doc.data()});
})
})

Categories

Resources