i want to Update the "key" in the flutter hive. but it is updating the value in a flutter.
updateItems(int index, String value){
final listData=Hive.box(CommonKeys.DB_NAME);
listData.putAt(index,value);
final keys=listData.keys;
I assume you want to change the key of element at an index.
Anwser is you can't do that directly (work around is really complicated, tell me if you really need it).
And you shouldn't do that, hive is a key-value pair database which mean it designed for read/write value using key or index. So you can't edit key or index, but you can assign that value to a new key.
In your case, I recommend you to store as List or Object instead
updateItems(int index, String newKey) {
final listData = Hive.box(CommonKeys.DB_NAME);
// This list has only 2 elements, key and value;
final List keyValuePair = listData.getAt(index);
keyValuePair[0] = newKey;
listData.putAt(index, keyValuePair);
}
Related
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).
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);
}
may i ask how to check if the map of String,String has in it's keys a specific String
then i want to get the value that belong this specific key that contains the target String.
for example
this Map
Map<String, String> ListFinalAllInfos = {'stackoverflow': 'one', 'google': 'two'};
and i want to check if this map has this String in it's keys
stackoverflow
if stackoverflow exists as a key inside the map then i want to get the value
which is
one
without converting the map to a list, if this possible.
thanks in advance
Map<String, String> ListFinalAllInfos = {'stackoverflow': 'one', 'google': 'two'};
String key = ListFinalAllInfos.containsKey("stackoverflow"); // search for the key. for example stackoverflow
String value = ListFinalAllInfos[key]; // get the value for the key, value will be 'one'
if(ListFinalAllInfos.containsKey(value)){ //check if there is a key which is the value you grabbed
return true;
}
You can use the containsKey(Object? key) method of map to know whether it is having a matching key. This method returns true if this map contains the given [key]. So in context to your question, to check whether map has this key just use:
final hasKey = listFinalAllInfos.containsKey("stackoverflow");
Now you know whether the map has the key or not. Based on that, to get value of respective key just use:
final valueOfKey = listFinalAllInfos["stackoverflow"];
This will return you the value associated to the key in the map.
I want to access keys and values in Dart without small brackets. As the values contain link I want String only. How can I achieve it?The output is with brackets as shown in the screen shot
This will loop through your code and show all the keys and values
Just loop through your ingredient list then loop through the map using the code below.
Map map = {};
map.forEach((key, value) {
print(key);
print(value);
});
I tried searching other questions but the only similar question to this had answers in JavaScript instead of Dart/Flutter. I'm trying to get a list from my Firebase Realtime Database into my app as a List<BaseModel>
So far from what I've searched in the net, I think the result of the DataSnapshot is a map that I could parse so I tried it out but got this error: List<dynamic>' is not a subtype of type 'Map<dynamic, dynamic>
My Code:
Future<List<BaseModel>> getList(
{DatabaseReference query, Models modelType}) async {
List<BaseModel> list = new List();
DataSnapshot snap = await query.once();
Map<String, dynamic> json = Map.from(snap.value);
json.forEach((key, value) {
list.add(BaseModel(model: modelType, key: key, snapshot: value));
});
return list;
}
The weird thing is, even if I try to parse a non-list model I also get the same error.
My database structure looks like this:
Update:
BaseModel:
abstract class BaseModel {
factory BaseModel({Models model, String key, Map map}) {
switch (model) {
case Models.MyModel:
return MyMod.fromSnapshot(key: key, map: map);
break;
default:
throw ("Not a valid model.");
}
}
}
MyModel:
MyModel.fromSnapshot({String key, Map map}) {
_id = key;
_title = map['title'];
}
My Firebase query is just the database reference with .child("Root")
I found a solution!
My new code:
Future<List<BaseModel>> getList({DatabaseReference query, Models modelType}) async {
List<BaseModel> list = new List();
DataSnapshot snap = await query.once();
List<dynamic> resultList = snap.value;
for(var i = 0; i < resultList.length; i++) {
Map<dynamic, dynamic> map = Map.from(resultList[i]);
list.add(BaseModel(model: modelType, key: i.toString(), snapshot: map));
}
return list;
}
This should work assuming you parse the values from your model's .fromMap(yourMap) constructor method. Something like _title = yourMap['key'];
I had a similar experience where the snapshot.value sometimes returned a List and sometimes returned a Map. I searched for a long time to get an answer with no luck but I came up with a workaround.
I suspected that the problem was being caused by using a record key with a value of zero so I added 100 to each key before I wrote it to the db and then subtracted it when I had read and was processing the records. The problem went away in that I then always got a Map returned.
I have since seen a reason given for this behaviour and it confirmed that the zero key value was the culprit but unfortunately I didn't save the link. I think it was on one of the Firebase blogs.
I think the 0 record returns a List and the ones with positive values return a Map.
Anyway, try the adding 100 trick and see it that helps. if it helps, upvote me....I don't think you need code to add or delete 100. :-)
Found the article, Firebase is deciding if it should render an array or a map based on the snapshot content: https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html?m=1
UPDATE:
My 'starting at 0' theory was a red herring, sorry.
The key to this behaviour (bits in bold) is in the part of the Firebase blog (link above) that states:
However, to help people that are storing arrays in Firebase, when you
call .val() or use the REST api to read data, if the data looks like
an array, Firebase will render it as an array.
In particular, if all of the keys are integers, and more than half of
the keys between 0 and the maximum key in the object have non-empty
values, then Firebase will render it as an array. This latter part is
important to keep in mind.
// we send this ['a', 'b', 'c', 'd', 'e'] // Firebase stores this {0:
'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
// since the keys are numeric and sequential, // if we query the data,
we get this ['a', 'b', 'c', 'd', 'e']
// however, if we then delete a, b, and d, // they are no longer
mostly sequential, so // we do not get back an array {2: 'c', 4: 'e'}
You can't currently change or prevent this behavior.
I have now tested this by setting up a db node that looks like the below image. I tested what was being returned in snapshot.value by using snapshot.value is List and snapshot.value is Map, both return true or false.
When ONLY nodes 0, 1 and 3 were there, Firebase RTDB was happily returning a List in snapshot.value. When I added nodes 4 and 6, which have inconsistent data, it decided it was time to return a Map. :-)
So, the quick fix is to test the contents of snapshot.value with is List and/or is Map and then process the contents accordingly, otherwise rethink your keys...the fact that they are sequential or close-to-sequential (with gaps) but have the same children structure is the issue.