I wrote a service to push a new data to my collection using update statement and I need to retrieve the id of last inserted data. I am using db.collection.update for this, but it just giving a response like this:
{
"result": {
"ok": 1,
"nModified": 1,
"n": 1
}
}
My api for that is:
app.post('/feeds',function(req,res) {
var _id = req.body._id;
var title = req.body.title;
var description = req.body.description;
var latitude = Number(req.body.latitude);
var longitude = Number(req.body.longitude);
db.user.update(
{_id:_id },
{$push : {
feed:{
title: title,
description:description,
latitude:latitude,
longitude:longitude
}
}
},function (err,result) {
if (err) {
res.json({"success": '0', "message": "Error adding data"});
}
else {
res.json({'result':result});
}
});
});
This is my Mongoose schema:
var user = new mongoose.Schema({
username : {type: String},
email : {type: String,index: {unique: true}},
password : {type: String},
feed : [{
title : {type: String},
description : {type: String},
latitude : {type:Number},
longitude : {type:Number},
feedImages : [{
imageUrl: {type: String}
}],
}]
});
I want to add data to feed.
My database structure
I want the id of newly pushed feed.
Embedded way (current schema)
If you want to use one document per feed and pushing sub-documents into (embedded way), you can pre-assign a _id to your newly created feed sub-document:
var feedId = new ObjectId();
db.user.update({
_id: _id
}, {
$push: {
feed: {
_id: feedId,
title: title,
description: description,
latitude: latitude,
longitude: longitude
}
}
}, function(err, result) {
/* ...your code... */
});
Don't forget to add a index for user.feed._id if you want to query for this field (using ensureIndex orcreateIndex depending of your mongodb version).
Using separate collection
As alternative way, you can use a separate feed collection, and use insert statements including a userId foreign key.
You can find more about pro/cons using Multiple Collections vs Embedded Documents here.
You should use db.user.insert() , why do you need the id, when you already have it from the req body?
db.user.insert(objectToInsert, function(err,docsInserted){
console.log(docsInserted);
});
It's a good case for findOneAndUpdate.
Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed.
Available options
new: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
Related
I am very much new in using mongoose and had done simple db work on mongodb.
Seeing my usecase I found this method of doing it in mongodb using mongoose. However I am not getting expected result as shown in tutorials.
My Schemas
var EventsSchema = new mongoose.Schema({
root: {type: mongoose.Schema.Types.ObjectId, ref: 'root'},
voting: [{type: mongoose.Schema.Types.ObjectId, ref: 'Voting'}]
});
var VotingSchema = new mongoose.Schema({
events: {type: mongoose.Schema.Types.ObjectId, ref: 'Events'},
title: {
type: String,
required: true
}
})
var Events = mongoose.model('Events', EventsSchema, 'event');
var Voting = mongoose.model('Voting', VotingSchema, 'voting');
I have these two schemas initially. I want to create a voting event. When voting event is created then in voting schema events id should be stored as suggested and more I want is that voting event reference should be stored in EventSchema.
var events = new Events({});
events.save()
.then((events) => {
var voting = new Voting({ events: events._id, title: "Test Title" });
voting.save()
.then((voting) => {
Voting.findOne({title: 'Test Title'})
.populate('events')
.exec(function(err, voting){
console.log(voting, err);
if(err) res.sendStatus(401).send();
else res.sendStatus(200).send();
})
})
.catch((e) => {
res.sendStatus(401).send();
});
})
.catch((e) => {
res.sendStatus(401).send();
})
What I am getting on console is
{
_id: 5b83eca82a3cfb1dec21ddc9,
events: { voting: [], _id: 5b83eca82a3cfb1dec21ddc8, __v: 0 },
title: 'Test Title',
__v: 0
}
My MongoDB looks like this
voting
{
"_id" : ObjectId("5b83eca82a3cfb1dec21ddc9"),
"events" : ObjectId("5b83eca82a3cfb1dec21ddc8"),
"title" : "Test Title",
"__v" : 0
}
events
{
"_id" : ObjectId("5b83eca82a3cfb1dec21ddc8"),
"voting" : [],
"__v" : 0
}
I am not sure how will my mongodb look like. But after attempting the code once it looks like above.
I must be doing something wrong or missing something important. But this kind of code is there in docs too. docs link. Help me in sorting this issue.
Thanks
Array of ObjIds should be defined this way in schema:
var EventsSchema = new mongoose.Schema({
root: {type: mongoose.Schema.Types.ObjectId, ref: 'root'},
voting: {type: [mongoose.Schema.Types.ObjectId], ref: 'Voting'}//**array bracers**
});
Also calling population over a field of type array like root field will return an empty array in the res of the API, see query hit by mongoose.set('debug', true); you will notice that mongoose is searching in event model not root.
though you have to tell mongoose in the population method which model to use in order to get the population working, unless you tell mongoose which model to search in .
populate({path:'vooting',model:'vooting'})
This is my mongodb schema
var Client = new Schema({
name: String,
race: [{
name: String,
car: [{name: String}]
}]
});
I want to find a car by _id, something like this:
Client.findOne({
"race.car._id": req.body._id
}, {
"race.$.car": 1
}, function(err, client) {
//How to get the right car ?
client[ ? ].race[ ? ].car.name = "updated name";
//And sure, update the client
client.save();
});
But I don't know the best way, for the findOne and for the save.
I am trying to create an index on two fields of a schema that are to be unique and sparse in MongoDB using Mongoose as follows:
var ArraySchema = new Schema ({
user_id: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
event_id: {type: mongoose.Schema.Types.ObjectId, ref:'Event'}
}, {_id:false});
ListSchema.index({user_id:1, event_id:1}, {sparse:true, unique:true});
Which is then used in an array in the User schema as such:
var User = new Schema({
arrayType1 : {
type: [ArraySchema]
},
arrayType2 : {
type: [ArraySchema]
},
arrayType3 : {
type: [ArraySchema]
}
//More specifications for user schema...
});
However, when trying to save multiple users without the array field, errors are thrown for duplicate fields. The error in Mocha looks similar to this: array.event_id_1 dup key {null, null}. An example of a segment of code that would throw this error is as follows:
var user1, user2;
user1 = new User({
username : 'username1',
password : 'password'
});
user2 = new User({
username : 'username2',
password : 'password'
});
user1.save(function() {
user2.save();
});
Here is my reasoning behind making the the fields of ArraySchema unique and sparse: If the array field is specifed, I do not want the array to contain duplicate objects; however, the array field is not required, so there will be many Users that have null for this field. Obviously I cannot use field-level indices since there are multiple fields that would need an index (arrayType1, arrayType2, arrayType3).
It appears that doing this sort of thing is not supported, at least at this time. The alternative would be to create a compound index on these fields then whenever adding a new element to the field use user.arrayType1.addToSet(). Here is an example of how this would work:
ArraySchema:
var ArraySchema = new Schema ({
user_id: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
event_id: {type: mongoose.Schema.Types.ObjectId, ref:'Event'}
}, {_id:false});
ListSchema.index({user_id:1, event_id:1});
User schema:
var User = new Schema({
arrayType1 : {
type: [ArraySchema]
},
arrayType2 : {
type: [ArraySchema]
},
arrayType3 : {
type: [ArraySchema]
}
//More specifications for user schema...
});
Then I could declare new users as usual (as I did in the question); however, when I want to add a new element to arrayType1, for example, I would use the following line of code to add to new element only if it is not already there:
user.arrayType1.addToSet({user_id : user2._id, event_id : event._id});
user.save(function(err, result) {
//Callback logic.
};
Where user2 and event are defined earlier in the code and saved to the db. Alternatively I could use Mongoose's update function as such:
User.update({_id : user._id}, {
$addToSet : {
arrayType1 : {
user_id : user2._id,
event_id : event._id
}
}
}, function(err) {
//Callback logic.
}
);
I have the following Mongoose schema representing a moving object
var vehicleSchema = new Schema({
properties:{
obj:String,
name:String,
id:String
},
geometry : {
type: {type : String},
coordinates : [ Number, Number ]
}
});
and I am trying to update it with the following object and command which work flawlessly if I enter in mongo console but does not update the document when used in a node function.
This is the object to be updated:
var updatedVehicle = new Vehicle(
{properties:{
obj:"Answer",
name:"is",
id:"42"
},
geometry:{
type:"Point",
coordinates:[42,42]
}
})
And this is the update command
Vehicle.update(
{$and:[
{'properties.obj':data.properties.obj},
{'properties.id':data.properties.id}
]},
{$set:
{properties:data.properties, geometry:data.geometry}
},
{upsert: true},
cb
)
I know that Mongoose has some quirks when it comes to GeoJSON and I hope this is just another one.
Your geometry schema property should just be set to an array of Numbers to store the coordinates, like so:
geometry : {
type: [Number],
index: '2dsphere` //some geospatial queries require this
}
and then query and updated as such
{ $set: { geometry: data.geometry.coordinates } }
I have this simplified Mongoose Schema:
UserSchema = new db.Schema({
_id : { type: db.Schema.Types.ObjectId,
name : { type : String },
friends : [{ type: db.Schema.Types.ObjectId, ref: 'User' }]
})
I want to get all friends with name that starts with a certain key string, let's say 'Pe' should return records 'Peter' and 'Petra'.
So I tried populating the friends field first:
user.Model
.findOne({
_id : loggedId,
})
.select('friends')
.populate('friends', 'name')
.exec(function(err, results) {
console.log(results);
});
That will return all the user's friends and their name which is not really what I want.
How do I return only those with a name that starts with certain characters?
TIA.
You can add options to the populate call.
See http://mongoosejs.com/docs/api.html#model_Model.populate