Manipulating data
Create and update
To write data to the DataStore, pass an instance of a model to Amplify.DataStore.save()
:
1Future<void> savePost() async {2 final newPost = Post(3 title: 'New Post being saved',4 rating: 15,5 status: PostStatus.INACTIVE,6 );7
8 await Amplify.DataStore.save(newPost);9}
The save
method creates a new record, or in the event that one already exists in the local store, it updates the record.
1Future<void> updatePost() async {2 final postsWithId = await Amplify.DataStore.query(3 Post.classType,4 where: Post.ID.eq('123'),5 );6
7 final oldPost = postsWithId.first;8 final newPost = oldPost.copyWith(id: oldPost.id, title: 'Updated Title');9
10 await Amplify.DataStore.save(newPost);11}
1class MyApp extends StatefulWidget {2 const MyApp({Key? key}) : super(key: key);3
4 5 State<MyApp> createState() => _MyAppState();6}7
8class _MyAppState extends State<MyApp> {9 StreamSubscription<QuerySnapshot<Post>>? _stream;10
11 // A reference to the retrieved post12 late Post _post;13
14 15 void initState() {16 super.initState();17 _configure();18 }19 20 // Initialize the Amplify libraries and call `observeQuery`21 Future<void> _configure() async {22 // ...23 }24 ...25
26 void observeQuery() {27 _stream = Amplify.DataStore.observeQuery(28 Post.classType,29 where: Post.ID.eq('123')30 ).listen((QuerySnapshot<Post> snapshot) {31 setState(() {32 _post = snapshot.items.first;33 });34 });35 }36
37 Future<void> updatePost(String newTitle) async {38 final updatedPost = _post.copyWith(title: newTitle);39 await Amplify.DataStore.save(updatedPost);40
41 // you do not need to explicitly set _post here; observeQuery will see42 // the update and set the variable.43 }44
45 // Build function and UI elements46 ...47
48 49 void dispose() {50 _stream?.cancel();51 super.dispose();52 }53}
Delete
To delete an item, simply pass in an instance.
Below, you query for an instance with an id
of 123
, and then delete it, if found:
1Future<void> deletePostsWithId() async {2 final oldPosts = await Amplify.DataStore.query(3 Post.classType,4 where: Post.ID.eq('123'),5 );6 // Query can return more than one posts with a different predicate7 // For this example, it is ensured that it will return one post8 final oldPost = oldPosts.first;9 try {10 await Amplify.DataStore.delete(oldPost);11 print('Deleted a post');12 } on DataStoreException catch (e) {13 print('Delete failed: $e');14 }15}
Query Data
Queries are performed against the local store. When cloud synchronization is enabled, the local store is updated in the background by the DataStore Sync Engine.
For more advanced filtering, such as matching arbitrary field values on an object, you can supply a query predicate.
1Future<void> readFromDatabase() async {2 try {3 final posts = await Amplify.DataStore.query(Post.classType);4 print('Posts: $posts');5 } on DataStoreException catch (e) {6 print('Query failed: $e');7 }8}
Predicates
Predicates are filters that can be used to match items in the DataStore. When applied to a query(), they constrain the returned results. When applied to a save(), they act as a pre-requisite for updating the data. You can match against fields in your schema by using the following predicates:
Strings: eq | ne | le | lt | ge | gt | contains | beginsWith | between
Numbers: eq | ne | le | lt | ge | gt | between
Lists: contains
For example if you wanted a list of all Post
Models that have a rating
greater than 4:
1Future<void> fetchPostsMoreThanFourRating() async {2 final posts = await Amplify.DataStore.query(3 Post.classType,4 where: Post.RATING.ge(4),5 );6 print('Posts: $posts');7}
Multiple conditions can also be used, like the ones defined in GraphQL Transform condition statements. For example, fetch all posts that have a rating greater than 4
and are ACTIVE
:
1Future<void> fetchPublishedWithRatingTwoPosts() async {2 final posts = await Amplify.DataStore.query(3 Post.classType,4 where: Post.RATING.eq(2).and(Post.STATUS.eq(PostStatus.ACTIVE)),5 );6 print('Posts: $posts');7}
Alternatively, the or
logical operator can also be used:
1Future<void> fetchPublishedOrWithRatingTwoPosts() async {2 final posts = await Amplify.DataStore.query(3 Post.classType,4 where: Post.RATING.eq(2).or(Post.STATUS.eq(PostStatus.ACTIVE)),5 );6 print('Posts: $posts');7}
Sort
Query results can also be sorted by one or more fields.
For example, to sort all Post
objects by rating
in ascending order:
1Future<void> fetchPostsInAscendingOrder() async {2 final posts = await Amplify.DataStore.query(3 Post.classType,4 sortBy: [Post.RATING.ascending()],5 );6 print('Posts: $posts');7}
To get all Post
objects sorted first by rating
in ascending order, and then by title
in descending order:
1Future<void> fetchPostsFirstInAscendingRatingOrderThenDescendingTitleOrder() async {2 final posts = await Amplify.DataStore.query(3 Post.classType,4 sortBy: [5 Post.RATING.ascending(),6 Post.TITLE.descending(),7 ],8 );9 print('Posts: $posts');10}
Pagination
Query results can also be paginated by passing in a page
number (starting at 0) and an optional limit
(defaults to 100). This will return a list of the first 100 items:
1// Do not forget to import the following with the other imports at the top of the file2import 'package:amplify_datastore_plugin_interface/amplify_datastore_plugin_interface.dart';3
4Future<void> fetchPostsWithPagination(int page) async {5 final posts = await Amplify.DataStore.query(6 Post.classType,7 pagination: QueryPagination(page: page, limit: 25),8 );9 print('Posts: $posts');10}