I'm using mongoose and I'm doing an update of my db by using findByIdAndUpdate() function. I'd like to push elements into different arrays present in my document. I have in my document different array with different names. May I pass as parameter the name array to this function or I should create different function where every function has a different nameArray?
this.findByIdAndUpdate(User._id,
{$push:{nameArray: 'element'}},
{upsert: true},
callback);
In Node.js 4.x you can use the computed property syntax to do this directly in the $push object literal:
this.findByIdAndUpdate(User._id,
{$push: {[nameArray]: 'element'}},
{upsert: true},
callback);
In previous versions, you need to build your $push object programmatically:
var push = {};
push[nameArray] = 'element';
this.findByIdAndUpdate(User._id,
{$push: push},
{upsert: true},
callback);
Related
Suppose I have 2 Schema's in Mongoose that look like this:
var movieSchema = mongoose.Schema({
name: String,
type: String
});
var moviePlaylistSchema = mongoose.Schema({
name: String,
movies: [{type: mongoose.Schema.Types.ObjectId, ref: 'Movie'}]
});
var Movie = mongoose.model('Movie', movieSchema);
var MoviePlaylist = mongoose.model('MoviePlaylist', moviePlaylistSchema);
If a query was made along the following lines:
MoviePlaylist.find({}).populate('movies').exec(function(err, res) {
if (err) console.log('err', err);
else {
console.log('res', res);
res.forEach(function(elem, index) {
console.log('elem.name', elem.name);
});
}
});
Would the order of the elements in the array be maintained? The objective here is to allow the user to maintain a playlist order of their movies. If, when the "populate" method fires, the array order of Movie object Ids is not maintained, then this will not serve my purpose. Hence thought I'd ask someone who is more knowledgeable in this area.
If this works, then I have another task which is allowing the user to change the order of movies in the playlist, which should be straight forward by allowing the movie object id index to be swapped in the array.
Thanks for your help in advance.
MongoDB will keep the order of the array, much like an array in any programming language.
You can view the BSON/JSON spec for reference which highlights that the array must contain integer values for keys, and be maintained in ascending numerical order.
Additionally, the Mongoose populate on an array works by calling Model.populate via forEach on each element of the array. This modifies the array in place, hence the order is preserved. You can see the relevant source code here.
I'm trying to add a new item to whichever name that was passed in under whichever id. My first problem is that it seems like its not grabbing the values from any of my variables (name, item, id), instead just using them as object keys. My next issue is that when I tested by hard-coding sample table info onto here, it wasn't adding more items to that array, but simply replacing the entire array with whatever values I had here.
function addlist(name, item, id){ // Add to user's list
console.log(id);
db.collection('newcon').update({_id: id}, { "$set": { "$push": { name:item } } });
ret(id);
}
$set is not an array update operation.
The $set operator replaces the value of a field with the specified value.
You just want to use $push by itself, as in
.update({_id: id}, {$push: {name: item}})
You can't interpolate object property names in raw object declarations, so if you want to use a variable name you will have to create an object to do this:
var obj = {};
obj[name] = item;
You can then pass this to .update, {$push: obj}
I have a mongodb collection with the following fields:
_id
name (string)
[items] (array of string)
secret (boolean)
I want to publish the all the _id, name fields and the item array length only (excluding the secret field) where the secret field is true.
I have read somewhere that I can add additional document properties in my find query, but my google foo does not work.
Here is what my publish method looks like without the additional items_count property:
Meteor.publish("all_items", function() {
return myItems.find(
{secret: true},
{fields:
{_id:1,name:1}
});
});
How can I create an additional field from the [item] length in my publication?
EDIT: it seems that I need to use an aggregate function and the $projectoperator. And it is not supported by meteor.
Can anyone confirm this to me (i.e. it is the only option and it is not supported)?
You can add aggregation framework support to Meteor, and then use a simple aggregation pipeline with $project stage as you mentioned, like to following:
myItems.aggregate(
[
{$match: {secret: true}},
{$project: {_id: 1, name: 1, items_count: {$size: '$items'}}}
]
)
Got a server returning a JSON object like so:
{
'key1':'value'
'key2':{
'key2_0':'value'
}
}
And a collection:
var Collection = Backbone.Collection.extend({
url:api.url//which returns the object above
});
var collection = new Collection();
collection.fetch({
success:function(data){
//do something
}
});
Now i need to use certain properties of the collection throughout my application, but say i need key1, i always have to do collection.at(0).get('key1');//returns 'value', because the data returned is stored within the collection, in a new Array at key 0.
Question:
How to directly... collection.get('key1')//now returns undefined... because it is.
I know i could expose an object to the global scope in the collection success function some_other_var = data.toJSON()[0] and access the some_other_var properties directly, but that's not what i'm looking for;
In order to use the get() function from a Backbone.Collection you need to know the model id or cid wanted.
For instance, lets say your data coming from the server is like follow:
[{
id: '123',
name: 'Alex'
}, {
id: '456',
name: 'Jhon'
}]
In that case you can do this:
this.collection.get('123').get('name') // Return "Alex"
Keep in mind that collection is just a set of model, so behind the scenes by doing collection.get() you are getting a model
Tip: If you don't have any kind of id in your server data, there is always the option of using underscore methods:
find
filter
some
contains
etc
It seems like you're trying to ascribe attributes to a collection, but a collection is merely a set of models. Having additional data that is constant throughout the collection suggests that it should be wrapped inside another Model, which is demonstrated here: Persisting & loading metadata in a backbone.js collection
I have the following string comming from server (as part of object):
...
SelectValues: "[{displayName: "Not selected", id: 0},{displayName: "Client", id: 1},{displayName: "Industry", id: 2},{displayName: "Country", id: 3}]"
...
I am using mapping pluging:
var ItemModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
}
As a result all items are created properly, except SelectValues. SelectValues should be observable array (each array item should have two properties id & displayName). Later I will use SelectValues for dropdown.
The problem is that it is returned as String and not as Array.
The question is whether I can somehow deal with it on client side (without changing format on server side)?
I probably can create SelectValuesComputed as ko.computed and somehow convert SelectValues to array (how?).
First of all, this is invalid JSON string you have in your property, see documentation (property names should be in quotes). But, having the condition that you cannot change the server code, you can use eval function to get your object and then use it in mapping like this:
var ItemModel = function (data) {
var self = this;
var mapping = {
"SelectValues": {
create: function(options){
return ko.mapping.fromJS(eval(options.data));
}
}
};
ko.mapping.fromJS(data, mapping, self);
}
See working demo. Although this might seem like the simpliest way to workaround the problem, I would strongly recommend you though to get a valid JSON string instead of using eval (or regexp) to get your object.