I want to duplicate an object in array in mongoose.
For example, if there is a object which projectName is "a", I want to create a complete same one, but the name is called "a duplicated".
I tried to the following code:
project.find({
"logininfo.username": username,
}, (err, users) => {
...
var user= users[0];
var dproject;
for(var i in user.projects){
if(user.projects[i].projectName === projectName)
{
dproject = user.projects[i];
break;
}
}
dproject.projectName += " duplicated";
dproject._id = new mongoose.Types.ObjectId();
user.projects.push(dproject)
projects.save((err, user) => {
...
However, this function will also change the previous object, which creates a completely same object (both names change to "a duplicated"), these two objects have the same _id.
How can I duplicate the object but keep the projectName and _id different?
Use JSON.parse(JSON.stringify(object)) to deep copy. It will make a copy but not a reference.
for (var i in projects.projects) {
if (projects.projects[i].projectName === projectName) {
dproject = JSON.parse(JSON.stringify(projects.projects[i])); //deep copy
break;
}
}
dproject._id = new mongoose.Types.ObjectId();
dproject.projectName += " duplicated";
projects.projects.push(dproject)
Related
I have a field of type map that contains Maps of data in firestore.
I am trying to retrieve this data using a cloud function in node.js. I can get the document and the data from the field but i can't get it in a usable way. I have tried every solution i can find on SO and google but the below is the only code that can give me access to the data. I obviously need to be able to access each field with in the Map individually. in swift i build an array of String:Any but i can get that to work in Node.JS
const docRef = dbConst.collection('Comps').doc('XEVDk6e4AXZPkNprQRn5Imfcsah11598092006.724980');
return docRef.get().then(docSnap => {
const tagets = docSnap.get('targets')
console.log(tagets);
}).catch(result => { console.log(result) });
this is what i am getting back in the console.
In Swift i do the following and am so far not able to find an equivalent in typescript. (i don't need to build the custom object just ability to access the keys and values)
let obj1 = doc.get("targets") as! [String:Any]
for objs in obj1{
let obs = objs.value as! [String:Any]
let targObj = compUserDetails(IDString: objs.key, activTarg: obs["ActivTarget"] as! Double, stepTarg: obs["StepTarget"] as! Double, name: obs["FullName"] as! String)
UPDATE
After spending a whole day working on it thought i had a solution using the below:
const docRef = dbConst.collection('Comps').doc('XEVDk6e4AXZPkNprQRn5Imfcsah11598092006.724980');
return docRef.get().then(docSnap => {
const tagets = docSnap.get('targets') as [[string, any]];
const newDataMap = [];
for (let [key, value] of Object.entries(tagets)) {
const tempMap = new Map<String,any>();
console.log(key);
const newreWorked = value;
tempMap.set('uid',key);
for(let [key1, value1] of Object.entries(newreWorked)){
tempMap.set(key1,value1);
newDatMap.push(tempMap);
};
};
newDatMap.forEach(element => {
const name = element.get('FullName');
console.log(name);
});
However the new data map has 6 seperate mapped objects. 3 of each of the original objects from the cloud. i can now iterate through and get the data for a given key but i have 3 times as many objects.
So after two days of searching an getting very close i finnaly worked out a solution, it is very similar to the code above but this works. it may not be the "correct" way but it works. feel free to make other suggestions.
return docRef.get().then(docSnap => {
const tagets = docSnap.get('targets') as [[string, any]];
const newDatarray = [];
for (let [key, value] of Object.entries(tagets)) {
const tempMap = new Map<String,any>();
const newreWorked = value;
tempMap.set('uid',key);
for(let [key1, value1] of Object.entries(newreWorked)){
tempMap.set(key1,value1);
};
newDatarray.push(tempMap);
};
newDatarray.forEach(element => {
const name = element.get('FullName');
const steps = element.get('StepTarget');
const avtiv = element.get('ActivTarget');
const UID = element.get('uid');
console.log(name);
console.log(steps);
console.log(avtiv);
console.log(UID);
});
}).catch(result => { console.log(result) });
I made this into a little function that gets the underlying object from a map:
function getMappedValues(map) {
var tempMap = {};
for (const [key, value] of Object.entries(map)) {
tempMap[key] = value;
}
return tempMap;
}
For an object with an array of maps in firestore, you can get the value of the first of those maps like so:
let doc = { // Example firestore document data
items: {
0: {
id: "1",
sr: "A",
},
1: {
id: "2",
sr: "B",
},
2: {
id: "3",
sr: "B",
},
},
};
console.log(getMappedValues(doc.items[0]));
which would read { id: '1', sr: 'A' }
I need to get a count of all the missing or empty fields in mongoose schema
The idea is to have a list of all the properties in a mongoose schema that are blank or does not have a value, so I can make a function to know what percentage of the document is missing.
I tried with count and count by null, but i don't know the query to get the results.
You can have a function like this in your application code:
const getDocumentCompleteness = (doc) => {
const totaFieldCount = Object.keys(doc).length;
let completedFieldCount = 0;
for(let key in doc) {
if(doc[key] !== undefined && doc[key] !== null && doc[key] !== '') {
completedFieldCount += 1;
}
}
return [totaFieldCount, completedFieldCount];
}
Whenever you need to get the completeness of a document, you can do this:
const [totaFieldCount, completedFieldCount] = getDocumentCompleteness(document);
// where document is the object representing the document you got from the database
I hope that helps.
I am new to firebase. I have data in Firebase realtime database with following structure. My requirement is to add a new field to multiple (selected) records present under “user”.
Initial Data
db—>user
—pushId_1 (Auto Generated via push command)
name: user1
pushId_2
name: user2
Required final Data with one more field added (“newField”)
db—>user
—pushId_1
name: user1
newField: sample data
pushId_2
name: user2
newField: sample data
I have written following code to do this.
exports.sampleFunction = functions.database.ref('/db/user/{pushId}/')
.onCreate((snap, context) => {
console.log('onCreate called with snapshot id = ' + snap.key);
admin.database().ref('/db/user/').once('value').then(snapshot => {
if (snapshot.numChildren() > 1) {
var updates = {};
var count = 0;
snapshot.forEach((child) => {
if (!child.hasChild('newField') && count < 2) {
updates[child.key] = { newField: 'sample data' };
count++;
}
});
//return snapshot.ref.set(updates); //set is also giving same result.
return snapshot.ref.update(updates);
}
return null;
}).catch(error => {
console.error("error in fetching data from db." + error);
});
return null;
});
Problem is, this code is deleting existing field "name" and replacing it with “newField”.
Can you please help me in appending this new field to data without deleting existing fields.
Thanks
That's because you are using set instead of updating the node.
Set replaces any content while update adds fields if missing and only replace fields if they are present in new data.
return snapshot.ref.update(updates);
Also you are setting the data wrong to update. In key you need to have path relative to the ref you are calling the update instead of nested objects.
Instead of updates[child.key] = { newField: 'sample data' };, it should be
updates[`${child.key}/newField`] = 'sample data';
now when you call update with the child parent i.e. snapshot, it knows exactly which fields to update.
See the docs for more details: https://firebase.google.com/docs/database/admin/save-data#section-update
I have two different subscriptions in my app:
Meteor.subscribe('collection');
and
Meteor.subscribe('filtered-collection',param1,param2);
I want to supply the data to different templates through different template helpers, say allResults and filteredResults respectively.
Since $geoWithin doesn't work at the client side and I need to use it for filtering, I cannot just filter the first subscription by
filteredResults = Collection.find(selector);`
Therefore, I need a separate subscription for it.
So, the question is: how to find the result set from respective subscription and pass it through a helper?
I finally solved the problem. I don't think the solution is ideal though.
At Server:
Collection = new Meteor.Collection('collection');
Meteor.publish('collection',function(){
return Collection.find();
});
Meteor.publish('filteredCollection',function(loc, radius){
var selector = {};
if (radius === undefined)
radius = 100;
if (loc !== undefined && !(isNaN(loc[0]) || isNaN(loc[1]))) {
selector.loc = {
$geoWithin: {
$centerSphere: [loc, radius / 6371]
}
};
}
var sub = this,
handle = null;
var handle = Collection.find(selector).observeChanges({
added: function(id, fields) {
sub.added("filteredCollection", id, fields);
},
changed: function(id, fields) {
sub.changed("filteredCollection", id, fields);
},
removed: function(id) {
sub.removed("filteredCollection", id);
}
});
sub.ready();
this.onStop(function() {
handle.stop();
});
});
At client:
Collection = new Meteor.Collection('collection');
FilteredCollection = new Meteor.Collection('filteredCollection');
Meteor.subscribe('collection');
Meteor.subscribe('filteredCollection',loc,radius);
Template.collection.helpers({
collection: function(){
return Collection.find();
},
filteredCollection: function(){
return FilteredCollection.find();
}
});
At the client, Collection and FilteredCollection are two different subsets of the same underlying collection at the server. But whether the two subsets are dependent on each other in terms of caching and persistence, is (I think) a different question altogether.
I'm trying to get the object id after adding it to the db (using collection.insert)
mongoose.model('Persons').collection.insert(person, function(err, newPerson) {
console.log('lets see you', newPerson);
});
and from the console I'm getting only result: { ok: 1, n: 1 } in stand of the new obj, any ideas how can I rich to the new object ?
thanks!
You can use save() here
var Persons = mongoose.model('Persons');
var personJSON = {
..... // persons schema values you want to insert
};
var person = new Persons(personJSON);
var result = yield person.save();
result variable will contain all the fields you inserted along with _id