Firestore Query For Non Existing Key of a Map - flutter

I am aware that it is possible to do null queries, for a field that has a null value.
In my case, I have documents containing a Map and I want to query all these that do not contain a given key. In my case, this key is a string formatted date.
I did try to do this with the following code but it is not working. Instead it fetches all documents:
Stream<List<Employee>> availableEmployeesForGivenDesignation(
String designation, DateTime date) {
// in firstore the keys of a map are Strings, thus I have to change DateTime to String
var formatter = new DateFormat('yyyy-MM-dd');
String formatedDate = formatter.format(date);
//todo check why I am getting with null also the false employees
return _employeeCollection
.where('designations', arrayContains: designation)
.where('busy_map.$formatedDate', isEqualTo: null)
.snapshots()
.map((snapshot) {
return snapshot.documents
.map((doc) => Employee.fromEntity(EmployeeEntity.fromSnapshot(doc)))
.toList();
});
}
To my understanding, I am querying on a map key and for some documents this key (date) does not always exist. This is why I tried to fetch these documents that return null on this case.
Database structure:

Found the answer...
I had to change the following line to:
.where('busy_map.$formatedDate', isNull: true)
So instead of using isEqual use isNull

Related

How to get the List of Document Reference from a Snapshot Document resulting from a Firestore query

I can't seem to figure out how to get a List after querying a specific Firestore collection.
I want the function to:
Query the 'chat' collection on the field 'users'.
Retrieve only the document (should be only one but could be an error and there's more than one) where users, which is a LIST of Document Reference, matches two specific references: chatUserRef and authUserRef
The function should return a list of the Document References referring to this chat collection
This is what I am trying:
import 'package:cloud_firestore/cloud_firestore.dart';
Future<List<ChatsRecord>> getChatDoc(
DocumentReference chatUserRef,
DocumentReference authUserRef,
) async {
// Add your function code here!
final firestore =
FirebaseFirestore.instance; // Get a reference to the Firestore database
final collectionRef =
firestore.collection('chats'); // Get a reference to the collection
final filteredDocuments = collectionRef.where('users', isEqualTo: [
authUserRef,
chatUserRef
]); // Use the `where` method to filter the list of documents
final queryDocuments = await filteredDocuments
.get(); // You can then use the get method on this Query object to retrieve the list of documents AS a Snapshot Document (this is NOT a list of the Documents themselves).
List<ChatsRecord> listChatDocs = [];
// Cast the Snapshot Documents to a map
// Extract the Document Reference ID
// cast the query document to a map for e
// (should I forEach?)
List<ChatsRecord> listChatDocs = queryDocuments.docs.map((e) {
return FirebaseFirestore.instance.doc('chats/$e.id');
}).toList();
return listChatDocs;
}
Try using the arrayContainsAny instead of EqualTo in your where clause.
Like this:
final filteredDocuments = collectionRef.where('users', arrayContainsAny: [
authUserRef,
chatUserRef
]);

How to correctly fetch data from firebase using where clauses and custom filters from firebase using flutter

Im trying to fetch data using
Stream<List<User>> getUsers(User user) {
return _firebaseFirestore
.collection('users')
// .where('interestedIn', isEqualTo: _selectInterest(user))
.snapshots()
.map((snap) {
return snap.docs.map((doc) => User.fromSnapshot(doc)).toList();
});
}
The filter used in the where clause is as follows
_selectInterest(User user) {
if (user.interestPreference == null) {
return ['HIRING', 'WORK'];
}
return user.interestPreference;
}
In firebase I store interestPreference as an Array with 'HIRING' as the only element in the current user's data, when I try to fetch users with 'HIRING' in their interestedIn which is a string I dont get any data. But when I hardcode the where clause as
.where('interestedIn', isEqualTo: 'HIRING')
I get the data, Can anyone help me solve my dilemma?
From that last query, it sounds like the interestedIn field in your database is a single string value, like interestedIn: "HIRING".
Your current query returns documents where interestedIn is an array with exactly the two values you specify, so interestedIn: ['HIRING', 'WORK']
If you want to return all documents where interested in is either "HIRING" or "WORK", you can use an IN condition:
.where('interestedIn', whereIn: ['HIRING', 'WORK'])
Or with your helper function:
.where('interestedIn', whereIn: _selectInterest(user))

How to filter firebase data using a where clause with FieldPat.documentId

Im trying to retrieve data with
Stream<List<User>> getUsers(User user) {
List<String> userFilter = List.from(user.swipeLeft!)
..addAll(user.swipeRight!)
..add(user.uid!);
return _firebaseFirestore
.collection('users')
.where('interestedIn', isEqualTo: 'HIRING')
.where(FieldPath.documentId, whereNotIn: userFilter)
.snapshots()
.map((snap) {
return snap.docs.map((doc) => User.fromSnapshot(doc)).toList();
});
}
I get an error
An error occurred while parsing query arguments, this is most likely an error with this SDK.
Invalid query. When querying with FieldPath.documentId() you must provide a valid document ID, but it was an empty string.
My data in firebase is structured as follows
How can I fix this?
In firebase you cannot filter with the document id, you can only filter with the fields in the document, a way a simple solution will be to generate a unique id by your self using packages like uuid and then save the document with the id and also save the id inside the document fields then you can filter with the id in the document field

How to update value within firestore query using dart

Here is a query that returns some data from the firestore database.
After getting the docs, I want to update a specific key(distance_away) value before returning the final List
return db
.collection(Global.marketplaceRef)
.where("point.geohash", isGreaterThanOrEqualTo: range.lower)
.where("point.geohash", isLessThanOrEqualTo: range.upper)
.limit(20)
.snapshots()
.map((list) => (list.docs
.map((e) {
// Update value here before returning doc.
// This doesn't seem to do that
return (e.data().update('distance_away', (value) => 100.toString())).toList();
})
).toList()
);
I want to alter the distance_away value of each doc.
You need to access the reference object not .data() try something like this
.map((list) => (list.docs
.map((e) {
return (e.reference.update({'distance_away': ['100']}
).toList()

How to sort this array of results?

Here is my query that attempts to sort an array of MongoDB documents based on a derived field called expiresAt. expiresAt is a Date object that represents the date string stored in doc.expirationDate.
It fails with an error TypeError: ... .sort({}) is not a function (shell):5
db.tokens.find().map(function(doc) {
var expiryDate = new Date(doc.credentialsMap.linkedin.expirationDate);
doc.expiresAt = expiryDate;
return doc;
}).sort({'expiresAt': -1});
What am I doing wrong? It's unclear to me exactly what return type map provides. If it's a cursor then why isn't sort supported? It's clearly available in the docs.
cursor.map() returns a Java script array.
The way you're calling sort() assumes that the return value is a MongoDB cursor, that's why it fails.
You'd have to use the regular Array.sort syntax.
For example, to have your map results sorted in descending order, use the following:
db.tokens.find().map(function(doc) {
var expiryDate = new Date(doc.credentialsMap.linkedin.expirationDate);
doc.expiresAt = expiryDate;
return doc;
}).sort(function(a,b) { return b.expiresAt - a.expiresAt});