Converting string to ObjectId is failing in mongoose 4.6.0 - node.js

I am trying to convert a string to ObjectId using
var body={};
var objId="57b40595866fdab90268321e";
body.id=mongoose.Types.ObjectId(objId);
myModel.collection.insert(body,function(err,data){
//causing err;
});
the above code is working fine when mongoose 4.4.16 is used, but if i update my mongoose to latest version(4.6.0) then problem occurs.
Err
object [
{
"_bsontype":"ObjectID",
"id:{"0":87,"1":180,"2":5,"3":235,"4":134,"5":111,"6":218,"7":185,"8":2,"9":104,"10":50,"11":111}
}
]
is not a valid ObjectId

The right way to insert new document is-
var newDocument = new myModel({
_id: mongoose.Types.ObjectId("57b40595866fdab90268321e")
});
newDocument.save();
In you case-
It stops working because the differences between versions of mongoose and mongo native drivers.
although, you are able to perform this by the example above, or, if you still want to use insert, you can use the myModel.insertMany (by passing object instead of array)
look here
http://mongoosejs.com/docs/api.html#model_Model.insertMany

I don't have the time to spike it, but if I remember correctly id is a simple string and _id is the ObjectId, i.e. either
body.id="57b40595866fdab90268321e"
or
body._id=mongoose.Types.ObjectId("57b40595866fdab90268321e");
That said, does it have to be that specific id? If not, you can use new myModel() and an id will be automatically created.

Related

Update by Id not finding document

I am attempting to perform a relatively simple update using Mongoose:
var location = locationService.getLocation(typedLat, typedLong, travelRadius);
DocumentModel.update({_id : passedInId }, { location : location }, function(err, resp){
next(err, resp);
});
In this case passedInId is the string:
"561ee6bbe4b0f25b4aead5c8"
And in the object (test data I created) the id is:
"_id": ObjectId("561ee6bbe4b0f25b4aead5c8")
When I run the above however, matched documents is 0. I assume this is because passedInId is being treated like a string, however when I type it to an ObjectId:
var queryId = ObjectId(passedInId)
The result is the same, the document doesn't match. What am I missing? This seems like it should be obvious....
Mongoose will correctly interpret a string as an ObjectId. One of the following must be the case:
That record is not in the collection. Run a query in the mongo shell to check.
Mongoose I'd looking in collection other than the one containing your test data. Remember, by default, mongo will lowercase the name under which you register your model and will add an a "s" to it.
Lastly, and your answer speaks to this, maybe your model it's just not being updated with any new information.
This behavior was because I had not yet updated the model in mongoose to include the location element. There is no error, it just doesn't match or do anything.

How do you find by id using the MongoDB Node driver?

I'm looking for the best way to find by id using the MongoDB Node driver.
I see that the _id field is an ObjectId, and so using a string for the id won't work. And I see that you could use ObjectId as follows:
var ObjectId = require('mongodb').ObjectId;
exports.show = function(req, res) {
var db = req.app.get('db');
var id = new ObjectId(req.params.id);
db.collection('posts').findOne({
_id: id
}, function(err, post) {
res.status(200).json(post);
});
};
But is there a best practice/more convenient way? I hadn't come across one in looking through the docs. Note: Mongoose has a findById method where you could just use the id string.
The _id field is already indexed, and findByID implicitly searches for one document, hence, findOne where you'll pass options {_id: id} as you're already doing.
As far as I understand, the major design consideration was to make native driver API similar to the mongo shell experience and keep it consistent all over the place (other drivers as well?). For this purpose you might want to keep API simple, yet powerful to cover all cases. So, to generalize, you have find() method and "a db.collection.findOne() method as a special case of find() that returns a single document."

MongoDB: Can I use a created ObjectId before saving my document

Using mongoose on node.js:
Can I access the _id field on a model before it has been saved to the database and be sure that the ID will not change?
For example, I would like to do the following:
var model = new mongoose.model('MyModel');
someOtherObject.myModelId = String(model._id);
// Some more code...
model.save(...);
In Mongoose, _id values must always be assigned client-side as the docs indicate that:
Mongoose forces the db option forceServerObjectId false and cannot be overridden.
So the model._id value you get in the first line of your code will not be changed unless you do it in your own code before calling model.save.

Set field to empty for mongo object using mongoose

I have a document object that has an embedded sub-document.
To "clear" the sub-document, I try this:
obj.mysub = {};
obj.save();
This doesn't work, my object still has the contents of the mysub sub-document.
But this:
obj.mysub = undefined;
obj.save();
This does work, it removes my sub-document from the object.
My question is why doesn't the first version work? What is going on in Mongodb / Mongoose in the first example?
[edit] Why doesn't the empty object get saved in the first example above.
Mongoose sort of "protects" you from a lot of logic like you have presented in it's own internal resolution. So if you actually need to do this then do it at a lower level to the driver as in:
YourModel.update(
{ /*statement matching your document as a query */ },
{ "$unset": { "mysub": 1 } }
)
And per the normal MongoDB logic then this will work and remove that level in the document that was selected. See the $unset operator for more.

Query Mongoose Schema by ObjectId

Going to need your help again, hopefully for this project, the answer to what I'm having here will be the last. I've seen it's a fairly commonly asked question, but I've tried the tips on another Stack Overflow post, and one by the Google Group, but the solutions haven't worked for me.
My code being a little bit like:
mongoose = require('mongoose');
Schema = mongoose.Schema;
mongoose.connect(MONGO_SERVER);
ObjectId = Schema.ObjectId;
var RacesSchema = new Schema({
venue_id : { type: mongoose.Schema.ObjectId, ref: 'Venues' },
racetype : String
});
var races = mongoose.model('Races', RacesSchema );
function test() {
var MyObjectId = require('mongoose').Types.ObjectId;
queryVenue = new MyObjectId("50e3dcdbf30375180c078f64");
races.find({venue_id: queryVenue, racetype:'Test'})
.exec(function(err,data) {
}
test();
But I get no results, which I know there is.
Many thanks in advance!
UPDATE
Have minimized the above code sample, this test works if I query the string value on its own, just querying for an ObjectId is where it fails, and I know it exists.
JSON UPDATE
Here is what I am looking for:
{
"_id" : ObjectId("50e3dcddf30375180c078f85"),
"venue_id" : "50e3dcdbf30375180c078f64",
"racetype" : "A"
}
And all of a sudden, I believe my answer has become clear to me. Is it simply because the venue_id is actually a string? And if so, can I keep my mongoose schema the way it is, and do casting on the query at the point of doing the find of being a string? Or should I change the way these values are being stored (from a separate .net application I developed) to be inserted as ObjectId's?
Currently right now for another query, the current mongoose schema and the way the database is [actually set up], using populate() works quite well to fill the results of the referenced table (venue_id) with the way this model is currently set up, only difference being on the above query, I don't specify the venue_id...
Thanks.
Right, the problem is happening because the data type of venue_id in the schema (ObjectId) doesn't match the one in the doc (String). So the find is looking for ObjectId values but doesn't find a match because it's a string in the doc.
The right fix for this is to write a little program to update the venue_id values in your docs to be ObjectIds instead of strings and then your query will work. That will also shrink the size of those fields from 24 bytes to 12.

Resources