The firebase documentation says this about updating in nested objects: https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects
My structure
let ref = db.collections('projects').doc('blabla')
ref.set({
objOfObjects: {}
})
I would like to add an object(value) with a randomly generated key to objOfObjects, much like the regular add function. I can't tie the key to any of the values of the object. Is there a way to add to objOfObjects or do I have to restructure my data?
There is no built-in function add a field with a randomly generated name to a document. But you can generate the random name yourself and add it. You can even use collection.add() to generate the random name, since (as Doug says here) that doesn't actually create a document yet.
var newId = store.collection('projects').doc().id;
let ref = db.collections('projects').doc('blabla');
var updates = {};
updates[id] = { ... }
ref.update(updates)
The tricks used here:
Get a new unique id, as explained before.
Use [] notation to use the value of that id as the property name.
Call update() to update a document, instead of replacing it.
Related
does anyone know how to push data to array in firebase without overwriting?
I use this solution, but unfortunately it overwrites the existing data:
db.collection('Goals').doc('Aqd8aP8uLSvuAgsMs5aW').update({"nested": ['12','14']})
If the items in the array are unique, you can use array union:
db.collection('Goals').doc('Aqd8aP8uLSvuAgsMs5aW')
.update({"nested": firebase.firestore.FieldValue.arrayUnion(['12','14'])})
If the items in the array are not unique, there is no way to do this with a single statement, and you will need to:
Read the document to get the array's current values.
Add the new values to the array in your application code.
Write the entire back to the document.
Also see:
How to update an "array of objects" with Firestore?
Adding already represented value in arraylist into arraylist
add object data to existing firebase document
According to the documentation https://firebase.google.com/docs/firestore/manage-data/add-data
you should merge data:
If the document does not exist, it will be created. If the document does exist, its contents will be overwritten with the newly provided data, unless you specify that the data should be merged into the existing document, as follows:
db.collection('Goals').doc('Aqd8aP8uLSvuAgsMs5aW').set({"nested": ['12','14']}, { merge: true });
You can use the Following syntax to solve the query
const handleOnSubmit = () =>{
const dataRef = db.database().ref(user['']);
const data = ({
*//data to push after every submit*
});
dataRef.push(data)
}
Possible it not best solution, but you can get current array and add new element.
const { nested } = await db.collection('Goals').doc('id');
nested.push('new element');
await db.collection('Goals').doc('id').update( { nested } );
The document in the target collection ("myCollection") has a field called "japanese2". This is an array (or an object) that contains an object that contains a property called "japanese2a". The value of this property is initially set to 0 (although it may change later). I want to change this value to 100 with a script in node.js (I am using the Express framework). The database is Mongodb, the free cloud version called Atlas.
If I do this without using variables, it works well:
db
.collection("myCollection")
.updateOne({username:username}, {"$set":{"japanese2.0.japanese2a":100}});
However, if I try this using variables for both the field name, "japanese2", and the name of the element/property in the array/object, "japanese2a", it fails. I have tried the below and other variations but I couldn't find a solution. I have researched stackoverflow for an answer but couldn't find a solution.
There is only one element/property in the array/object to start with.
var field = req.body.fieldName; //want to set this for the field name="japanese2"
var task = req.body.question; //want to set this for the name of the element="japanese2a"
var myField = [task];
field = myField;
var fieldPos = field[0];
.
.
.
db
.collection("myCollection")
.updateOne({username:username}, {"$set":{[fieldPos]:100}});
The above creates a new field called "japanese2a":100" but it does not appear in the array under the field called "japanese2", which is what I want.
I don't get any error messages when I do the above in the console (probably mostly due to the fact that I haven't put in error statements/functions to catch errors), but the output is not correct.
Another way of updating that I found from here:
https://www.codementor.io/#prasadsaya/working-with-arrays-in-mongodb-16s303gkd3
that involves using something like this:
db.posts.updateOne(
{ _id : ObjectId("5ec55af811ac5e2e2aafb2b9"), "comments.user": "Database Rebel" },
{ $set: { "comments.$.text": NEW_CONTENT } }
)
doesn't work for me, as I don't know if the initial value of the element in the array will always be a zero or some other constant. And there is only one element in the array initially. I can only use the username for the match part in the updating. I can't make an expression that is a perfect match for some element in the array.
The update solution from here: MongoDB update data in nested field
db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });
works, and that is what I used successfully to update in the first updating attempt above, but I don't know how to incorporate variables into the updating operation, specifically a variable for the field name ("japanese2") that holds the array or the object, and the name of the first and only element/property in the array/object ("japanese2a").
EDITED: I asked for a solution for an "array" originally, but either a field that acts an array (that holds elements that act as objects) or an object (that holds other objects as properties) works in my case, so I edited the question body and title. Also, the accepted solution works with the field as an entity that holds an array, or as an entity that contains an object inside it.
In either case, if there is already a field with the appropriate name, an object is created (if it didn't already exist) as an object of that object called "field" or the array called "field", and the object's property is set as according to the variables in the script.
If the field doesn't exist, it's created (as an object), and this object contains another object that contains the property ("task" as the name and "100" as the value for the name-value pair). So the newly created "field" object contains an object as its property. The property of this object is a name-value pair of "japanese2a" and "100".
If the script is run again, with a different "task" name (eg. "japanese2b"), another property is created, with the name of "japanese2b" and the value of "100". It is created within that same object that is "inside" the "field" object, so the object field.0 (the object within the "field" object) ends up looking like this: {japanese2a: 100, japanese2b: 100}. And the object called "field" looks like this: {{japanese2a: 100, japanese2b: 100}}.
I think something like
var field = req.body.fieldName // japanese2
var task = req.body.question; // japanese2a
var updateObj = { $set : {} };
updateObj.$set[field + '.0.' + task] = 100
db
.collection("myCollection")
.updateOne({username:username}, updateObj);
Might work
You can quite easily set a data attribute of any element with jquery using $('#elid').data('key', value). You can do the same using document.querySelector('#elid').setAttribute('data-key', value)
However, jQuery gives you a special ability that querySelector doesn't - the ability to add attributes of an arbitrary type (including functions, and I think promises, which is what I need).
So if you were to do $('#elid').data('key', function(){console.log('yes')}) with jQuery, and then $('#elid').data('key')(), it would log 'yes' to the console -- we can just assign a function to the element as a data attribute and run it whenever.
But we can't do the same with 'setAttribute' -- when we do it, it apparently just assigns a stringified form of the function to the data attribute, rather than the actual function.
I've provided example code here:
https://jsfiddle.net/8e1wyL41/
So how can I apply data to elements with plain javascript, just like jQuery, including the ability to have arbitrary functions or javascript objects as data attribute values?
jQuery#data() uses an internal object to keep track of data values. It does not update the element to have new or changed data-* attributes when setting data values. When retrieving a data value, if the internal object does not have a set value it will attempt to get it from the data-* attributes.
A overly simplified way of doing this without jQuery would be to just use an object and store your data on that
var element = document.querySelector("div");
element.customData = {};
//get data example, check if customData has a value first, if not use dataset
var someData = element.customData["somedata"] || element.dataset["somedata"];
//set
element.customData["somedata"] = function(){};
If you don't want to contaminate the element with arbitrary properties you could use a WeakMap, pending on browser support, to associate a data object with the element. This also allows for using a single object to maintain other element data objects as well. The key to the data object is the element object itself. And the data object will get deleted from the map automatically once the element is garbage collected
var dataMap = new WeakMap();
var element = document.querySelector('div');
var elementData = dataMap.get(element);
if(!elementData){
dataMap.set(element, elementData = {});
}
//get data example, check if data object has a value first, if not use dataset
var someData = elementData["somedata"] || element.dataset["somedata"];
//set
elementData["somedata"] = function(){};
.dataset sets or gets a DOMString of HTML data-*, though you can use Function() to call the function stored as string at HTMLElement.dataset
document.documentElement.dataset.fn = function fn(...args) {console.log(args)};
new Function("return " + document.documentElement.dataset.fn)()("yes");
I have some JSON data where I define presets with a unique identifier ID, (you could call it a primary key). Besides ID there are a bunch of other properties defined, including somethingelse. I want to extract the somethingelse property of a particular record, identified by its ID. I tried this:
function getSomethingElse(id) {
return presets[id].somethingelse;
}
But obviously the above code will only access the preset with array position id. I'm trying to access the preset where the actual ID is id.
This might be a dumb question, but I haven't been able to find any example of what I'm trying to do!
If ID is used as a primary key then I'd suggest converting your preset data to a hashmap instead of an an array.
var presets= {};
presets["guid1"] = "hello"
presets["guid2"] = "world"
This should work exactly as your posted code intends.
Assuming $scope.presets is an array, You need to iterate your objects like
$scope.loadPreset(id) {
angular.forEach($scope.presets, function(value, key) {
if(value.id == id){
$scope.somethingelse = value.somethingelse;
}
});
}
I am trying to create an associative array in JavaScript:
<script>
var cst_dta = new Array('name' => 'amar', 'total_bill' => 'akbar', 'phone' => 'anthony');
$(document).ready(function(){
alert(cst_data);
});
</script>
But the above code is not alerting anything! What's wrong with the array?
Didn't it occur to you that JavaScript isn't PHP?
This is simply not the correct syntax.
Use:
var cst_dta = {
'name' : 'amar',
'total_bill' : 'akbar',
'phone' : 'anthony'
};
You have much more details on object literals (and other literals) on this page.
You can use objects as associative arrays:
var cst_dta = {name:'amar',total_bill:'akbar',phone:'anthony'};
And you can access it as,
cst_data['name'] or cst_data['phone'] or ..
But it doesn’t seem very useful in this case. Here cst_data.name is fine to use.
Basically, objects are used as associative arrays to bind arbitrary strings to arbitrary values, usually dynamically. Like for example, here you are getting a stock name value from the user at runtime:
var stock_name = get_stock_name_from_user();
var shares = get_number_of_shares();
portfolio[stock_name] = shares;
Since the user enters stock names at runtime, there is no way that you can know the property names ahead of time. Since you can't know the property names when you write the program, there is no way you can use the . operator to access the properties of the portfolio object.
You can use the [] operator, however, because it uses a string value (which is dynamic and can change at runtime) rather than an identifier (which is static and must be hardcoded in the program) to name the property.