Mongoose reference not placing ObjectId in parent document - express

My Mongoose model is not placing ObjectId's in the parent document for referencing to the subdocument in another collection. How can I do this?
These are my models:
menu_items.js
var menuItems = new mongoose.Schema({
title : String,
subitem: [{type: mongoose.Schema.Types.ObjectId,ref: 'sub_items'}]
}, {collection: 'menu_items'});
module.exports = mongoose.model("menu_items", menuItems);
sub_items.js
var subItems = new mongoose.Schema({
title: String,
},{collection: 'sub_items'});
module.exports = mongoose.model("sub_items", subItems);
My subitem post function in ExpressJS:
postController.postSubitems = function(req,res,item) {
var id = req.body.id;
var saveData = {
title: req.body.sub_item
};
var data = new item(saveData);
saveToDB(data,res);
};

You also need to update your menuItem as well. For example, say the _id of your new sub_item is 123456. You need to update your menuItem like so:
menuItem.subitem.push(123456);
menuItem.save();
This will add the _id to the subitem array, and thus give the menuItem a reference to the specified sub_item

Related

Using reference in Mongoose with ExpressJS

Since I've noticed that deep nesting arrays in documents is not good practice, I wanted to use references in Mongoose using ExpressJS. Now I am making a CMS where there are menu items which the user can post. Each menu item can have sub items that the user can also post. But I don't know how to use referencing so I can reference between the main items collection and the sub items collection.
This is my Main_items Mongoose model:
var menuItems = new mongoose.Schema({
title : String,
subitem: {
type: mongoose.Types.ObjectId,
ref: 'sub_items'
}
}, {collection: 'menu_items'});
module.exports = mongoose.model("menu_items", menuItems);
And the sub_items model:
var subItems = new mongoose.Schema({
title: String,
});
module.exports = mongoose.model("sub_items", subItems);
Post of main_menu items
postController.postMainItems = function(req,res,item){
var saveData = {
title : req.body.title
};
var data = new item(saveData);
saveToDB(data,res);
};
I already created a post for the main menu items. That works. But now I want to know how I can post the sub items so they are directly referenced to each main item
Change the Schema as below, So that you need to insert the main menu first with title and then sub menu with title and parent(_id of parent main menu).
Main Menu Schema:
var menuItems = new mongoose.Schema({
title : String
}, {collection: 'menu_items'});
module.exports = mongoose.model("menu_items", menuItems);
Sub Menu Schema:
var subItems = new mongoose.Schema({
title: String,
parent: { type: mongoose.Types.ObjectId, ref: 'menu_items'}
});
module.exports = mongoose.model("sub_items", subItems);

Update only changed fields in Mongoose

I'm trying to update a subdocument using ExpressJS and Mongoose. But only the fields that are changed. but somehow it updates all necesary field but also the fields that don't need to be changed.
This is the Update function in ExpressJS:
postController.updateMessage = function(req, res, item) {
var id = req.body.id;
var saveData = {
title: req.body.title,
text: req.body.text,
title_double: req.body.title_double,
text_double: req.body.text_double
};
item.findOneAndUpdate({'subitem.messages._id': id}, {$set:{'subitem.$.messages': saveData}}, {upsert: true, new: true},(error, result) => {
console.log(result);
console.log(error);
});
};
And this is the Mongoose Model:
var submessages = mongoose.Schema({
date: String,
type: String,
title: String,
text: String,
title_double: String,
text_double: String
});
var subitems = new mongoose.Schema({
title: String,
messages: [submessages]
});
var menuItems = new mongoose.Schema({
title : String,
subitem: [subitems]
}, {collection: 'menu_items'});
module.exports = mongoose.model("menu_items", menuItems);
you have two nested array while your are check/condtions on one array
{$set:{'subitem.$.messages.$': saveData}}
something like that on your condition

find subdocument without start from parent

Pretty new to mongoose. Can I findOne off of a subdocument model?
I have a subdoc called deliverables which is a child of projects
What I'd like to do is FIND on my deliverables model so I don't have to find on the project as
{project.child.child.child.deliverables._id: req.id}
Is that possible or do I have to start from the project model each time? Below is a sample setup I'm using along with my example findOne.
'use strict';
//////////////model/////////////////
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var deliverablesSchema = new Schema({
title:{
type:String,
}
})
var ProjectSchema = new Schema({
name: {
type: String,
},
deliverables: [deliverablesSchema],
});
mongoose.model('Deliverable', deliverablesSchema);
mongoose.model('Project', ProjectSchema);
//////////////controller/////////////////
var mongoose = require('mongoose'),
Project = mongoose.model('Project'),
Deliverable = mongoose.model('Deliverable'),
_ = require('lodash');
exports.findDeliverable = function(req, res) {
Deliverable.findOne({'_id': req.params.deliverableId}).exec(function(err, deliverable) {
if(deliverable){
//return
}
});
};
You can find subdocuments within a document only if you have declared their schema http://mongoosejs.com/docs/subdocs.html
Here is an example taken from here:
Project.findOne({
'_id': myid
}).exec(function (err, p) {
if (p) {
//return
var deriv = p.deliverables.filter(function (oneP) {
return oneP._id === 'myderivableid';
}).pop();
}
});
If your subdocuments are just nested objects in an array you may use Lodash to retrieve that data using _ .where or _.find
Kept digging and found this:
https://stackoverflow.com/a/28952991/2453687
You still have to pull the master document first but it's easy to drill down to the particular object you're looking for and make a quick update, then just update the whole master document in one shot.
Dead simple. Works like a charm.

Ext JS 4 - how to change content of an item which can't be referenced by an ID

I would really appreciate any help with the following problem:
I need to be able to change content of an item (div or textfield) but the problem is that there are going to be multiple instances of the same window so I cannot use div IDs.
I tried this little example:
var myBtnHandler = function(btn) {
myPanel.items.items[0].html = "Changed by click!";
myPanel.doLayout();
}
var fileBtn = new Ext.Button({
text : 'Change',
handler : myBtnHandler
});
var panel1 = {
html : 'Original content.'
};
var myPanel = new Ext.Window({
title : 'How to change it?',
items : [
panel1,
fileBtn
]
});
myPanel.items.items[0].html = "Changed on load!";
myPanel.show();
Referencing an element by myPanel.items.items[0] works on load but does not work when it's in the button handler - is it a scope-related problem? How to reference an element without its ID?
Thank you very much,
H.
The problem has nothing to do with scope. The first time you set the html property, the component has not yet been rendered, so on initial render it will read the html property off the component. The second time, you're just setting a property on an object, it's not going to react in any way.
Instead, you should use the update() method.
Ext.require('*');
Ext.onReady(function() {
var myBtnHandler = function(btn) {
myPanel.items.first().update("Changed by click!");
}
var fileBtn = new Ext.Button({
text: 'Change',
handler: myBtnHandler
});
var panel1 = {
html: 'Original content.'
};
var myPanel = new Ext.Window({
title: 'How to change it?',
items: [panel1, fileBtn]
});
myPanel.items.items[0].html = "Changed on load!";
myPanel.show();
});
There are several functions that go through elements that belongs to a container. Try using for example down():
btn = panel.down('button');
Where 'button' parameter would mean 'give me element which type is equal to 'button'. Check out Sencha doc for querying various elements too: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.ComponentQuery
Following on from Sha's reply. To put his advice in context with your example.
var myBtnHandler = function(btn) {
btn.up('window').down('panel').update('Changed by click!');
}
var fileBtn = new Ext.Button({
text : 'Change',
handler : myBtnHandler
});
var panel1 = {
html : 'Original content.'
};
var myPanel = new Ext.Window({
title : 'How to change it?',
items : [
panel1,
fileBtn
]
});
myPanel.show();
myPanel.update('Changed on load!');

How to add (remove) new items to an existing dataSource in Dashcode?

I have a question concerning DashCode and dataSources: I have defined an JSON object in javascript file, linked it to a dataSource and connected the company names to the user interface (a 'list' element). The JSON object looks like:
{
items: [
{ company:'A', product:'a1', color:'red' },
{ company:'B', product:'b2', color:'blue' },
{ company:'C', product:'c3', color:'white' }
]
}
How do I programmatically add (or remove) an additional "item" to the existing dataSource? I have used the following approach:
function addElement() {
var newElement = [{company:'D', product:'d4', color:'yellow' }];
var ds = dashcode.getDataSource('list');
ds.arrangedObjects.addObject(newElement);
}
and
function delElement()
{
var ds = dashcode.getDataSource('list');
if (ds.hasSelection()) {
var index = ds.selectionIndex();
ds.arrangedObjects.removeObjectAtIndex(index);
}
}
This piece of code indeed adds (removes) an additional item to the dataSource. However, when I use the list.filterpredicate to search the list for the new item, the new item is ignored.
What is the 'correct' approach to add (or remove) an item to an existing dataSource programmatically?
Your help is being appreciated!
Here is an answer to the question:
1) Define a KVO object in main.js. This step is important to make the object bindable:
anObj = Class.create(DC.KVO, {
constructor: function(company, product, color) {
this.company = company;
this.product = product;
this.color = color;
}
});
2) The updated version of the function 'addElement' is:
function addElement() {
var newElement = new anObj('D', 'd4', 'yellow');
var ds = dashcode.getDataSource('list');
var inventory = ds.valueForKeyPath('content');
inventory.addObject(newElement);
}
3) The updated version of the function 'removeElement' looks similar:
function delElement()
{
var ds = dashcode.getDataSource('list');
if (ds.hasSelection()) {
var index = ds.selectionIndex();
var inventory = ds.valueForKeyPath('content');
inventory.removeObjectAtIndex(index);
}
}
I hope this information helps!