Push or add to collection in mongoose - arrays

I have a lot of objects I'm saving to Mongoose. They are deep objects.
var obj1 = {
first_name : 'adam',
last_name: 'smith',
car : [{
make: 'honda',
model: 'civic',
colors: [{
name: 'red',
code: 'ff0000'
}]
}]
}
Going in to a matching model like so:
var Owner = new Schema({
first_name: String,
last_name: String,
cars:[{
make: String,
model: String
colors: [{
name: String,
code: String
}]
}]
});
Which is all fine and dandy, unless adam has a second record:
var obj2 = {
first_name : 'adam',
last_name: 'smith',
car : [{
make: 'ford',
model: 'focus',
colors: [{
name: 'blue',
code: '0000ff'
}]
}]
}
var obj3 = {
first_name : 'adam',
last_name: 'smith',
car : [{
make: 'honda',
model: 'civic',
colors: [{
name: 'blue',
code: '0000ff'
}]
}]
}
Each overwrites the previous one completely when I do something like:
Owner.findOneAndUpdate({first_name:"adam", last_name: "smith"}, obj2, {upsert: true});
How do I get mongoose to create a new record when there isn't one, but append to the car array when there is? And if the car already exists, append to the colors array?
To make things a little more fun, the structure of the data is not consistent in my case. It is for a given collection, but each of my collections are being set up dynamically, so the model may be many layers deep and have any given keys.

This approaches allows you to push a new element onto an array field
db.findOneAndUpdate(
{first_name:"adam", last_name: "smith"},
{ $push: { cars : {
make: 'ford',
model: 'focus'
}
}
},
{ safe: true,
upsert: false,
new : true
}
);
I feel your pain regarding trying to guess syntax for arbitrarily complex insert/update/deletes ... the world of mongo/mongoose is screaming for a tool to read Schemas/data and let you interactively describe your particulars to synthesize code snippets like above

Related

Mongoose: Update by pushing an object in an array

This is the model I am working with:
name: {
type: String
},
payment: {
id: {
type: String,
required: true
},
cards: [
{
id: {
type: String
},
is_default: {
type: Boolean,
"default": false
}
}
]
}
I want to add a card to the cards array, for example:
card =
id: "some_token"
is_default: true
I am using the update method to push the card to the array, but it won't add the card to the document. Instead, it creates a new document with only those fields:
{
id: "some_token",
is_default: true,
_id: someId
}
Any idea how I can update the actual document I am targeting instead of creating a new document?
Here's my code (using CoffeeScript):
update_where =
payment:
id: "some_id"
update_push =
$push:
'payment.cards':
id: card_token
is_default: false
Customer.update update_where, update_push, {upsert: true}, (err, results) ->
# Do something with the results
Oh… I just noticed my mistake. The problem was in the where statement.
I was doing:
payment:
id: "some_id"
But the right thing to write is the following:
'payment.id': 'some_id'
And it now works!

Mongoose - insert object with array to mongo DB

I'm using Mongo for the first time and I'm having difficulties with creating a document which has an array.
The object is passed to a nodejs server like so:
{
"customerid":"121212",
"name": "Zero 2679",
"email": "a#a.com",
"address": "bla bla bla",
"tokens":[{"ctoken":"123456"},{"ctoken":"1234567"}]
}
The code executes the following:
var newCustomer = new Customer(
{
_id: request.body.customerid,
name: request.body.name,
email: request.body.email,
address: request.body.address,
tokens:request.body.tokens
});
newCustomer.save(function (err) {
if (err) winston.log('error', err);
// saved!
})
The schema is configured like so:
var customerSchema = new Schema({
// index: true => Tells mongo to index this paramater because it is used frequently. It makes querying faster
_id: {type: String, unique: true}, // unique customer ID
name: {type: String, default: '', required: true}, // Customer name
//email: {type: mongoose.SchemaTypes.Email, required: true},
email: {type: String, required: true},
address: { type: String, required: true },
toknes: [{ ctoken :{type: String} }]
}, {collection: 'customers'});
When I go and look at the object in the MongoDB, it looks like this:
{
"_id": "121212",
"email": "a#a.com",
"address": "bla bla bla",
"tokens": [],
"name": "Zero 2679",
"__v": 0
}
The tokens are missing and there's a '_v' value which I don't even have.
Please advise what am I doing wrong?
in your schema
tokens: [{ ctoken : String }]
request.body.tokens must be something like = {ctoken: 'some string'}
var newCustomer = new Customer(
{
_id: request.body.customerid,
name: request.body.name,
email: request.body.email,
address: request.body.address,
tokens:[request.body.tokens]
});
newCustomer.save(function (err) {
if (err) winston.log('error', err);
// saved!
})
and if the customer db documents contains data, then you should perform push operation
In your schema it should be:
tokens: [{ type: String }]
As ctoken is not a data type. The working schema is illustrated below:
var customerSchema = new Schema({
_id: {type: String, unique: true},
name: {type: String, default: '', required: true},
email: {type: String, required: true},
address: { type: String, required: true },
tokens: [{ type: String }]
}, {collection: 'customers'});

OrderBy with enumerable property in AngularJS

I have an object array where every object can have an array of properties, like this
[
{
name: 'Big house',
properties: [{name: 'Area',value: '400'}, {name: 'Year',value: '1950'}]
},
{
name: 'Small house',
properties: [{name: 'Area',value: '400'}, {name: 'Year',value: '1950'}]
},
{
name: 'Green house',
properties: [{name: 'Area',value: '40'}, {name: 'Year',value: '2008'}]
},
{
name: 'Red house',
properties: [{name: 'Area',value: '250'}, {name: 'Year',value: '1999'}]
},
];
Now I'd like to order this list by one of the properties, say Area, using a filter in ng-repeat. Is that possible?
I've been play around with this in plunker (http://plnkr.co/edit/GEgLxv5zJyW0ZBTtJR5S?p=preview) but cannot figure out how to do.
Thanks in advance
This will work if the area is always the first property:
<tr ng-repeat="house in houses | orderBy:'properties[0].value'">
Also make sure that the area is defined as an integer, right now they are strings. So 250 will be sorted before 40.
So remove the quotes from the numbers:
{
name: 'Area',
value: 400
}
, {
name: 'Year',
value: '1950'
}

Ext.data.TreeStore modified the data source after the tree is rendered?

Let's say I have the data source as following:
var data = [
{
id: 1,
name: 'name1',
parentId: null,
children: [
{
id: 2,
name: 'name2',
parentId: 1
}
]
},
{
id: 3,
name: 'name3',
parentId: null,
children: [
{
id: 4,
name: 'name4',
parentId: 3
}
]
}
]
And the code snippets like following:
var basic_grid_store = Ext.create('Ext.data.TreeStore', {
storeId: 'basic_grid_store',
model: 'TestModel',
root: {
children: []
}
});
console.log(data);
// the data structure is correct at this time
basic_grid_store.setRootNode({children: data);
console.log(data);
// the data structure is incorrect at this time, in which the `children` attribute for each item was gone.
I could not find any documentation for this, can someone tell why TreeStore modified my data source since it should not happen?
Yeah, it does change the original array. I cannot answer why this behavior, you would need to ask Ext architects/developers, but what you can try is:
basic_grid_store.setRootNode({children:Ext.clone(data)});

Backbone-UI, TableView, rendering columns

I'm trying to render a table view with four columns, 'name', 'birthday', 'gender', 'married', but
a) they columns aren't showing up at all
b) I'm not even sure if I am passing them correctly, because when I console.log table.options the columns property is rendered as "empty":
Object {columns: Array[0], emptyContent: "no entries", onItemClick: function, sortable: false, onSort: null}
I've tried this:
var table = new Backbone.UI.TableView({
model: people,
columns: [
{ title: "Name", content: 'name' },
{ title: "Gender", content: "gender" } },
{ title: "Birthday", content: "birthday" } },
{ title: "Married", content: "married" } }
]
});
And this:
var table = new Backbone.UI.TableView({
model: people,
options: {
columns: [
{ title: "Name", content: 'name' },
{ title: "Gender", content: "gender" },
{ title: "Birthday", content: "birthday" },
{ title: "Married", content: "married" }
]
}
});
The source code change is adding the options as mu is too short said. Change the initialize method of the Backbone.UI.TableView object to be the following within the source code:
initialize : function(options) { //add parameter
Backbone.UI.CollectionView.prototype.initialize.call(this, arguments);
$(this.el).addClass('table_view');
this._sortState = {reverse : true};
this.options = _.extend({}, this.options, options); //Add this line
}
I'm sure there might be a better place to put this but I'm just going through tutorials to learn some advanced backbone stuff considering the documentation does not match the current version I would shy away from using the library in production as of right now. Hopefully it is fixed in the future.

Resources