i've been googling around about how to add an object into an array in firestore, and found the arrayUnion() able to add an object into firestore array, but it only add the object into last index of array, but how to add it into first index of array?
//add "greater_virginia" into last index of array
washingtonRef.update({
regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});
//how to add "greater_virginia" into first index of array?
its basically same as arrayUnion but instead of add it into last index, i want to add it into first index of array.
If Firestore arrays behave anything like realtime-database arrays, then they don't actually exist. As far as I know, they are store as maps, like:
{
0: "first element",
2: "second and so on",
}
You can probably see how an unshift would be a big transformation. In fact, firestore doesn't let you do this, saying "...in order to avoid some of the issues that can arise in a multi-user environment, you'll be adding them with more of a set-like functionality".
With that in mind, this problem is usually solved at the application level by fetching the array, mutating it as needed, then setting the whole thing.
Bit of further reading https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
PS: be careful with the arrayUnion operator, because it actually performs a add to set
Firestore doesn't offer any way to modify items of array fields by index. arrayUnion will only ever append to the end of the array if the element doesn't already exist.
If you want to modify an array by index, you will have to read the document, modify the array in memory to appear how you want, then write the modified array back to the document.
Related
I would like to update the completed property of an object in an array in Firestore, but I have no idea how to reach that specific element in the array. The image will show the structure.
I have come up this far but don't know how to choose, for example, item 1 in the array. I was thinking of using its ID (it has an id property) but don't know how to get there.
const businessRef = db.collection('approvedBusinesses').doc(businessId)
try {
businessRef.update({
[`bookings.${currentDate} ????? `]: true // what to add after currentDate?
})
By the way, this is how the array was created (and how other objects are pushed to it)
const bookingObj = {
carro: 'PASSA_CARRO',
completed: false,
userId: userObject.uid,
}
businessRef.update({
[`bookings.${currentDate}`]: firebase.firestore.FieldValue.arrayUnion(bookingObj),
})
Firestore does not have an operation that allows you to update an existing item in an array by its index.
To update an existing item in the array, you will need to:
Read the entire document into your application.
Modify the item in the array in your application code.
Write back the entire array to the document.
I'm pretty sure this has been asked before, so let me see if there's an answer with an example.
Also see:
How to remove an array element according to an especific key number?
Simple task list ordering - how to save it to Firebase Firestore?
How to update only a single value in an array
How to update an "array of objects" with Firestore?
Suppose this scenario.
I have a collection where I store products, this products have a property called "props" and this is an array of objects, that have properties like measure, weight.
The problem comes when I'm trying to insert new products. I'm receiving an array of objects that will be inserted, but each element of the array could have a property called "propsReference", and If it's there, it would be an ID that refers to the object that's currently inserted and have some props
So, if it has the propsReference property with an ID, I want to copy the properties of this object to the object I'm going to insert
The only solution I can think of is doing a foreach to the first array, if it has the propsReference do a query, get the props and insert it into this element of the array as a new property of the object.
But I'm having a lot of problems with doing queries inside a for loop, there's any way in mongoose or something to avoid that?
Thanks in advance
I have a firestore firebase database , in which I have a collection users
there is an array in the collection and in the array there is a map
in map there is a field qty.. I want to increment that qty value..
using increment doesnt help as the qty is inside a array index
db.collection("users").doc(checkId).update({
myCart: firebase.firestore.FieldValue.arrayUnion({
qty: firebase.firestore.FieldValue.increment(1),
}),
this is the error Output =>
Uncaught (in promise) FirebaseError: Function FieldValue.arrayUnion() called with invalid data. FieldValue.increment() can only be used with update() and set()
My answer below won't work, given that the qty is in an array. The only way to update an item in an array is to read the entire document, update the item in the array, and then write the entire array with the updated item back to the document.
An alternative would be to use a map instead of an array, and then update the qty using the approach outlined in my (old, and non-working) answer below 👇
You need to specify the full path to the field you're trying to update. So I think in your case, that'll be:
db.collection("users").doc(checkId).update({
"myCart.0.qty": firebase.firestore.FieldValue.increment(1)
}),
The field you want to update is embedded in an array. In this case, you can't use FieldValue.increment(), since it's not possible to call out an array element as a named field value.
What you'll have to do instead is read the entire document, modify the field in memory to contain what you want, and update the field back into the document. Also consider using a transaction for this if you need to update to be atomic.
(If the field wasn't part of an array, you could use FieldValue.increment().)
As of today (29-04-2020)... this is tested by me.
Suppose my data structure is like this:
collection: Users
Any document: say jdfhjksdhfw
It has a map like below
map name: UserPageVisits
map fields: field1,field2,field3 etc
Now we can increment the number field in the map like below:
mapname.field1 etc...
That is use the dot operator to access the fields inside the map just like you would do to an object of javascript.
JAVA Code (Android), update the field using transactions so they can complete atomically.
transaction.update(<documentreference object>,"UserPageVisits.field1",FieldValue.increment(1));
I have just pushed a version of my app which uses this concept and it's working.
Kudos !!
My Best Regards
Previous answers helped me as well, but dont forget about the "merge" property!!! Otherwise it will overwrite your entire array, losing other fields.
var myIndex = 0;
const userRef = db.collection('users').doc(checkId);
return userRef.update({
'myCart.${myIndex}.qty': admin.firestore.FieldValue.increment(1)
}, {
merge: true
});
At the moment I am storing a few objects in Firebase. After successfully retrieving the items from Firebase and storing them in a firebaseArray, I want to further thin out the unwanted elements by deleting the elements in the firebaseArray that do not have the desired property. Consider my code at the moment, that does not do as wanted, however there are no errors in the console:
var querylatestPosts = firebase.database().ref("Topics");
$scope.latestPosts = $firebaseArray(querylatestPosts);
console.log($scope.latestPosts) ;
$scope.latestPosts.forEach(function(el) {
if ($scope.checkWorldview(el) == false) {
delete $scope.latestPosts.el ;
}
});
(Note I am unable to log 'el' in the console, nor does the forEach seem to execute, as I can log nothing in the function in the console)
The 'checkWorldview' function behaves as expected when elements are fed in different instances and returns false if the required property is not present in the element under consideration. Thus if the function returns false, I want to delete the specific element in $scope.latestPosts that does not contain the wanted property.
I hope this is clear, thank you in advance for any help you can offer!
The way you are using the $firebaseArray isn't recommended by the docs (see here), which state that $firebaseArray is read only and should not be manipulated.
So you have a few options:
Instead of filtering the array on the client-side, you should modify the query you're using to retrieve data from Firebase to only get elements that have the desired property (ex: use 'equalTo' in the query)
OR
Don't use a $firebaseArray because you're not using it in the way it was intended. Use a regular, good ol' fashion JavaScript array instead.
** Also, just a general comment: don't delete elements from an array as you loop through it as this is generally bad practice (we don't expect arrays to have elements added/removed while we loop through them). Instead, use Array.filter.
I'm building an Entity System for a game, and basically I'm not sure whether I should use simple objects (dictionaries) or arrays to to store the entities/components by their id.
My biggest issue is that I didn't want a dynamic entity id. If the id was just a string (using the dictionary to store entities), then it would always be valid and I could use storage[id] to get to that entity.
If I used arrays, I thought, the id's of entities, which would represent an index in the storage array, would change. Consider this array of entities:
[
Entity,
Entity, //This one is being removed.
Entity
];
If I was to remove the second entity in that array, I thought that the id required to access the third array would have to change to the id (index) of the (now removed) second entity. That's because I thought about deleting in terms of splice()ing.
But, I could use the delete expression to turn the element (an entity) into an undefined! And, if it's true that arrays in Javascript are actually just objects, and objects logically have infinitely many undefined values, does that mean that undefined values inside arrays don't use up memory?
Initially, I though that arrays were implemented in a way that they were aligned in memory, and that an index was just an offset from the first element, and by this logic I thought that undefined values would use at least the memory of a pointer (because I, actually, thought that pointers to elements are aligned, not elements themselves).
So, if I stored 10k+ entities in this array, and deleteed half of them, would the 5k undefined's use any memory at all?
Also, when I do a for entity in array loop, would these undefined elements be passed?
Also, where can I find resources to see how arrays are actually supposed to be implemented in Javascript? All I can find are general explanations of arrays and tutorials on how to use them, but I want to find out all about these little quirks that can prove important in certain situations. Something like a "Javascript quirks" site would be great.
Arrays are not just objects. In particular the length property is very magic.
Of course, a JavaScript engine is allowed to represent the array internally in any way it chooses, as long as the external API remains the same. For instance, if you set randomly separated values then they may be stored as a hash, but if you set consecutive values then they may be optimised into an array.
for ... in does not enumerate properties that are not set. This includes an array literal that skips values e.g. [true, , false], which will only enumerate indices 0 and 2.