Sembast read only 1 item - flutter

How can I read only 1 item from NoSql using Sembast? Every article about reading items are showing me creating a list but I only need just 1 item from databse.

You can access any record using the RecordRef api (and extension): https://pub.dev/documentation/sembast/latest/sembast/SembastRecordRefExtension.html
// Lint warnings will warn you if you try to use different types
var store = intMapStoreFactory.store();
// add a record, autogenerate a key
var key = await store.add(db, {'offline': true});
// Reading a single record falue
var value = await store.record(key).get(db);

Related

How do I only return my primary keys from a Firebase RTDB and not the rest of the data stored when using a get() in Flutter?

My menu item tree looks is shown below:
menuItem
J1
-description:"Tasty milk shake!"
-img:"assets/images/milkshake.JPG"
-itemName:"Milk Shake"
-price:20
-varieties
-var1:"Chocolate"
-var2:"Vanilla"
-var3:"Strawberry"
I want to get just the item IDs (J1, J2, J3 ect.) but not all the information such as 'itemName'
final DatabaseReference _dbRef = FirebaseDatabase.instance.ref();
final items = await _dbRef.child('menuItem').get();
if (items.exists) {
String? itemID = items.value.toString();
}
items.values returns all the information for an item and items.key returns only 'menuItem'.
How can I just get the IDs only?
With the Realtime Database queries done via the Client SDKs are deep: They always return the entire subtree.
This is a key difference with Firestore for which queries are shallow: They only return documents in a particular collection or collection group and do not return subcollection data.
However, with the Realtime Database REST API you can use a query parameter named shallow, which "limits the depth of the data returned at a location". I've never used it but it seems that it will fulfill your requirement.
Another solution would to denormalise your data and maintain, in parallel to the menu items, a list of menu IDs in a specific DB node.
As Renaud explained in his answer, all read operations in the Firebase Realtime Database SDKs return complete branches of the tree, and can't be used to just read the keys.
That said, you can use just the keys from the data you read with:
final DatabaseReference _dbRef = FirebaseDatabase.instance.ref();
final items = await _dbRef.child('menuItem').get();
items.forEach((child) => {
console.log(child.key);
})
The above will still retrieve the entire menuItem branch of your database, but only show the keys under that node (so J1 from the sample you shared).

Read nested data from firebase realtime database in flutter

If you see the screenshot of my database, the data is stored in a nested way (cartProduct is a key which has a value of an entire Json file with keys: "id", "price" etc.). In my code, I create a map of each record in the "Orders" table in order to retrieve key values of any key that I specify. This is done by specifying the key name in the databaseMapper variable.
I am trying to read the value of each "id" and store it in a list called "testerList". I am able to store each orderNum, totalAmount or any of those key values that I specify in the databaseMapper. However, if I specify ["id"] it does not work.
I did some research and saw that the only way to reference nested items in a map is by using the logic: databaseMapper["cartProduct"]["id"] like I did below, but I keep getting an error (see last screenshot).
Any help would be appreciated!
Future _readItemIDsTest() async {
//Stores each record in the table as a map
var snapshot = await _dbRef.child("Orders").get();
snapshot.children.forEach((childSnapshot) {
var databaseMapper = childSnapshot.value as Map;
testerList.addAll([databaseMapper["cartProduct"]["id"]]);
});
print(testerList);
}
Nvm, I figured it out. The code below solved my issue.
Future _readItemIDsTest() async {
//Stores each record in the table as a map
//Adds the itemName value of each item from the map
var snapshot = await _dbRef.child("Orders").get();
snapshot.children.forEach((childSnapshot) {
databaseMapper = childSnapshot.value as Map;
var cartProductList = databaseMapper["cartProduct"];
(cartProductList as List).forEach((cartProductElement) {
testerList.addAll([cartProductElement["id"]]);
});
});
print(testerList);
}

DynamoDB - How to upsert nested objects with updateItem

Hi I am newbie to dynamoDB. Below is the schema of the dynamo table
{
"user_id":1, // partition key
"dob":"1991-09-12", // sort key
"movies_watched":{
"1":{
"movie_name":"twilight",
"movie_released_year":"1990",
"movie_genre":"action"
},
"2":{
"movie_name":"harry potter",
"movie_released_year":"1996",
"movie_genre":"action"
},
"3":{
"movie_name":"lalaland",
"movie_released_year":"1998",
"movie_genre":"action"
},
"4":{
"movie_name":"serendipity",
"movie_released_year":"1999",
"movie_genre":"action"
}
}
..... 6 more attributes
}
I want to insert a new item if the item(that user id with dob) did not exist, otherwise add the movies to existing movies_watched map by checking if the movie is not already available the movies_watched map .
Currently, I am trying to use update(params) method.
Below is my approach:
function getInsertQuery (item) {
const exp = {
UpdateExpression: 'set',
ExpressionAttributeNames: {},
ExpressionAttributeValues: {}
}
Object.entries(item).forEach(([key, item]) => {
if (key !== 'user_id' && key !== 'dob' && key !== 'movies_watched') {
exp.UpdateExpression += ` #${key} = :${key},`
exp.ExpressionAttributeNames[`#${key}`] = key
exp.ExpressionAttributeValues[`:${key}`] = item
}
})
let i = 0
Object.entries(item. movies_watched).forEach(([key, item]) => {
exp.UpdateExpression += ` movies_watched.#uniqueID${i} = :uniqueID${i},`
exp.ExpressionAttributeNames[`#uniqueID${i}`] = key
exp.ExpressionAttributeValues[`:uniqueID${i}`] = item
i++
})
exp.UpdateExpression = exp.UpdateExpression.slice(0, -1)
return exp
}
The above method just creates update expression with expression names and values for all top level attributes as well as nested attributes (with document path).
It works well if the item is already available by updating movies_watched map. But throws exception if the item is not available and while inserting. Below is exception:
The document path provided in the update expression is invalid for update
However, I am still not sure how to check for duplicate movies in movies_watched map
Could someone guide me in right direction, any help is highly appreciated!
Thanks in advance
There is no way to do this, given your model, without reading an item from DDB before an update (at that point the process is trivial). If you don't want to impose this additional read capacity on your table for update, then you would need to re-design your data model:
You can change movies_watched to be a Set and hold references to movies. Caveat is that Set can contain only Numbers or Strings, thus you would have movie id or name or keep the data but as JSON Strings in your Set and then parse it back into JSON on read. With SET you can perform ADD operation on the movies_watched attribute. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.ADD
You can go with single table design approach and have these movies watched as separate items with (PK:userId and SK:movie_id). To get a user you would perform a query and specify only PK=userId -> you will get a collection where one item is your user record and others are movies_watched. If you are new to DynamoDB and are learning the ropes, then I would suggest go with this approach. https://www.alexdebrie.com/posts/dynamodb-single-table/

How to show list in flutter whose id matches

I have two list of data stored in
1. final profiles = context.watch<ProfilesBloc>().state.profiles;
2. final users= context.watch<UsersBloc>().state.users;
I want to build the list with the only whose profile.id matches the user.id
I tried by if (user.id == profiles.id) but it's not working
any help?
var newUser = users.where((user) => user.id.toLowerCase().contains(profiles.id.toLowerCase()).toList();
you can basically use this method to check a condition to create a new list. Feel free to alter the codes as per your requirements.

Ionic 2 Storage - Adding Records

I am new to the NoSQL world and since Ionic 2 by default supports simple key-value DB, I was to some help here.
My app has a very large form. How do I go about saving new records? How do I retrieve those particular records?
Currently, to save a new record, I am doing something like this:
save(data){
let newData = JSON.stringify(data);
this.storage.set('reports', newData);
}
The problem with this is it overwrites the record instead of inserting a new record.
I am retrieving records like this:
getData() {
return this.storage.get('reports');
}
How do I go about fetching a particular record using certain values in the stored JSON?
Thanks.
What you would have to do is make reports as an array and set it to the storage.
everytime you need to insert a new record, do a
function(newData){
var some_variable = storage.get('reports'); //get Existing Table
some_variable.push(newData); //Inserts the new record to array
storage.set('reports', some_variable); //Saves report with updated data
}
For getting a particular report alone, I hope you have some id or a unique attribute y which you can distinguish a report. Assuming you have the report json as below :
var report {id : "UniqueID", name : "A sample report json"}
Then to get the report,
function(reportId){
var reports = this.storage.get('reports');//fetches your reports Array
var wantedReport = {};//Variable to store the wanted report
reports.forEach(function(r){ //Looping the array.You can use a forloop as well
if(r.id === reportId){ //filtering for the wanted reportId
wantedReport = r; // storing the report to variable
}
})
return wantedReport; //Returning the report to the caller.
}
Alternatively, If you are used to Sql and want a Sql-like way of storing these data then you can install the Sqlite cordova plugin and store your data in a Sqlite DB.