firestore_model
Easy way to use firestore collection with data model
Adding Firestore Model to your project
In your project's pubspec.yaml
file,
- Add firestore_model latest version to your dependencies.
# pubspec.yaml
dependencies:
firestore_model: ^<latest version>
Config
void main() async {
await FirebaseApp.initializeApp(
settings: FirestoreModelSettings(
//persistenceEnabled: true,
));
runApp(MyApp());
}
Data Model
- define your model
User
- extend model with
FirestoreModel
with your model Type
class User extends FirestoreModel<User> {
}
- override
toMap
&&responseBuilder
class User extends FirestoreModel<User> {
String? firstName;
String? lastName;
User({this.firstName, this.lastName});
// use to read
User.fromMap(Map<String, dynamic> map) {
this.firstName = map['first_name'];
this.lastName = map['last_name'];
}
// use to write
@override
Map<String, dynamic> get toMap => {
'first_name': this.firstName,
'last_name': this.lastName,
};
@override
ResponseBuilder<User> get responseBuilder => (map) => User.fromMap(map);
}
- we plural model name and use it as collection name in this example collection name will be
users
. - if you wont to change collection name override
collectionName
in your model.
@override
String get collectionName => 'users';
Inject Model
- Inject your Model
FirestoreModel.inject(User());
- Inject All your Models
FirestoreModel.injectAll([User()]);
- retrieve your model
FirestoreModel.use<User>();
Create
To Write in data base:
- prepare your data model like this:
User user = User(firstName: "Mohamed", lastName: "Abdullah 3");
- call
create
method from your model like this:
user.create();
- return document as a model;
- if you have id for doc:
user.create(docId: 'hdoihvnoirejiu9345j');
Save
- use save to create or update model.
- make changes to your model and call
save
:
user.firstName = 'new firstname';
user.save()
Update
- update specific fields in your model call
update
:
user.update(data: {
"first_name": "Mohamed",
"last_name": "Abdullah"
})
- update specific model use
update
by pass docId:
FirestoreModel.use<User>().update(
docId: 'hdoihvnoirejiu9345j',
data: {
"first_name": "Mohamed",
"last_name": "Abdullah"
})
delete
- delete current model call
delete
:
user.delete();
- delete specific model use
delete
by pass docId:
FirestoreModel.use<User>().delete(docId: 'hdoihvnoirejiu9345j')
Exists
- check if document is exists call
exists
by docId:
bool isExists = await FirestoreModel.use<User>().exists('hdoihvnoirejiu9345j')
Find
- To get document data by document id call
find
:
User user = await FirestoreModel.use<User>().find('hdoihvnoirejiu9345j')
- To stream document data by document id call
streamFind
:
Stream<User> streamUser = FirestoreModel.use<User>().streamFind('hdoihvnoirejiu9345j')
All
- To get all documents call
all
:
List<User> users = await FirestoreModel.use<User>().all()
- To stream all documents call
streamAll
:
Stream<List<User>> streamUsers = FirestoreModel.use<User>().streamAll()
First
- To get first result from your collection call
first
: - you can build your query like
where
orderBy
or any query buildr methods:
User firstUser = await FirestoreModel.use<User>().first(
queryBuilder: (query) => query.where('score', isGreaterThan: 100)
.orderBy('score', descending: true)
);
Get
- To get results from your collection call
get
: - you can build your query like
where
orderBy
or any query buildr methods:
List<User> topUsers = await FirestoreModel.use<User>().get(
queryBuilder: (query) => query.orderBy('score', descending: true).limit(10)
);
- To stream results from your collection call
streamGet
:
Stream<List<User>> topUsers = await FirestoreModel.use<User>().streamGet(
queryBuilder: (query) => query.orderBy('score', descending: true).limit(10)
);
Pagination
- To get results limit and load more as pagination from your collection call
paginate
. - you can build your query like
where
orderBy
or any query buildr methods. - you can set
perPage
in your call or set in your model
List<User> topUsers = await FirestoreModel.use<User>().paginate(
perPage: 15,
queryBuilder: (query) => query.orderBy('score', descending: true),
);
- To stream results from your collection call
streamPaginate
:
Stream<List<User>> topUsers = await FirestoreModel.use<User>().streamPaginate(
perPage: 15,
queryBuilder: (query) => query.orderBy('score', descending: true),
);
Builders
ModelSingleBuilder
: getfirst
orfind
by docId.
ModelSingleBuilder<User>(
// your query to get first result
query: (q) => q.orderBy('createdAt'),
// pass document id if you need to get only this document
docId: 'iuiouurpoeuriqwe',
builder: (_, snapshot) {
// your widget
});
ModelGetBuilder
: get documents with anyquery
.
ModelGetBuilder<User>(
// your query to get results
query: (q) => q.orderBy('createdAt'),
builder: (_, snapshot) {
// your list builder
});
ModelStreamGetBuilder
: streamget
documents with anyquery
.
ModelStreamGetBuilder<User>(
// your query to stream results
query: (q) => q.orderBy('createdAt'),
builder: (_, snapshot) {
// your list builder
});
ModelStreamSingleBuilder
: streamfirst
orfind
by docId.
ModelStreamSingleBuilder<User>(
// your query to stream first result
query: (q) => q.orderBy('createdAt'),
// pass document id if you need to stream only this document
docId: 'iuiouurpoeuriqwe',
builder: (_, snapshot) {
// your widget
});
Builder Listener
you can listen to any builder:
* onLoading
=> fire when builder is loading.
* onChange
=> fire when your data in stream builder changed.
* onSuccess
=> fire when builder return data
* onError
=> fire if error in query
* onEmpty
=> fire if builder success but data is empty
onChange: () {
print("Data Change");
},
onLoading: () {
return Center(
child: Text("Loading"),
);
},
onEmpty: () => Center(
child: Text("Sorry Your List is Empty"),
),
onSuccess: (data) {
//return builder widget;
},
onError: (error) => print("Error $error"),
FieldValue
increment
: increment field value
// this increase user score by 1;
user.increment(field: 'score');
// this increase user score by 2;
user.increment(field: 'score', value: 2);
decrement
: decrement field value
// this decrease user score by 1;
user.decrement(field: 'score');
// this decrease user score by 2;
user.decrement(field: 'score', value: 2);
arrayUnion
: union elements to array
// append 'kotlin' to user languages
user.arrayUnion(field: 'languages', elements: ['kotlin']);
arrayRemove
: remove elements from array
// remove 'kotlin' from user languages
user.arrayRemove(field: 'languages', elements: ['kotlin']);
remove
: remove field from document
// remove 'languages' field from user document
user.remove(field: 'languages');
SubCollection
SubCollection
is a collection associated with a specific document.
Prepare SubCollection Model
- create
Model
forSubCollection
and extends model withSubCollectionModel
with your model Type:
class Post extends SubCollectionModel<Post> {
}
- override
toMap
&&responseBuilder
- we plural model name and use it as collection name in this example collection name will be
posts
. - if you wont to change subCollection name override
subCollectionName
in your model
@override
String get subCollectionName => 'posts';
Create in SubCollection
- use parent to work with subCollection
Post post = user.subCollection<Post>();
post.title = "new test Title For post ${DateTime.now()}";
post.description = "Description Title in post Sub collection";
post.create();
Update document in SubCollection
// use `update` to update document in subCollection
post.update(data: {'title': 'updated title'});
// or you can use `save`
post.description = 'new description';
post.save();
if you have SubCollectionModel
you can work as any FirestoreModel
Builder With SubCollection
- to use builders to retrieve subCollection Documents you must be have
parentModel
ModelStreamGetBuilder<Post>(
// parent model for Post SubCollectionModel
parentModel: user,
builder: (_, snapshot) {
// your list builder
}
);