Flow Router doesn't work with ObjectID. Any fix? - mongodb

I'm trying to build routes in my Meteor app. Routing works perfectly fine but getting information from db with route path just doesn't work. I create my page specific routes with this:
FlowRouter.route('/level/:id'...
This route takes me to related template without a problem. Then I want to get some data from database that belong to that page. In my template helpers I get my page's id with this:
var id = FlowRouter.getParam('id');
This gets the ObjectID() but in string format. So I try to find that ObjectID() document in the collection with this:
Levels.findOne({_id: id});
But of course documents doesn't have ObjectIDs in string format (otherwise we wouldn't call it "object"id). Hence, it brings an undefined error. I don't want to deal with creating my own _ids so is there anything I can do about this?
PS: Mongo used to create _ids with plain text. Someting like I would get with _id._str now but all of a sudden, it generates ObjectID(). I don't know why, any ideas?

MongoDB used ObjectIds as _ids by default and Meteor explicitly sets GUID strings by default.
Perhaps you inserted using a meteor shell session in the past and now used a mongo shell/GUI or a meteor mongo prompt to do so, which resulted in ObjectIds being created.
If this happens in a development environment, you could generate the data again.
Otherwise, you could try to generate new _ids for your data using Meteor.uuid().
If you want to use ObjectId as the default for a certain collection, you can specify the idGeneration option to its constructor as 'MONGO'.
If you have the string content of an ObjectId and want to convert it, you can issue
let _id = new Mongo.ObjectID(my23HexCharString);

Related

want to use _id instead of id in waterline with mongodb

I have a case where I need to change the default referencing of primary key name id with _id for all the models in a given project I am working.
There is an express.js + mongoose setup which is in production. The data present in the database is directly referred by our users using mobile application. And the code of mobile application is very much aware of reading _id as the key in all the documents it receives in JSON.
Since sails uses waterline which has default key name as id and it maps to _id for mongodb, the underlying database will be used as it is, however on the middleware we are always reading it as id.
I have searched through the web and tried to have default id name as _id in the config/models.js, but the schema creation outputs an error stating _id, _id is used twice.
Production database, Waterline ... I recommend against actually changing your primary keys. Heck, I'd recommend against that kind of monkey-wrench if you were using a much more mature ORM.
Instead, I say, transform the key names in your action. e.g. in an action2, where you just return template variables at the end of a function:
r = await Model.findOne(where);
return {
_id: r.id, // <---- this bit <----
etc: r.etc
}
And then make a JSON structure as your view template.

Meteor React - Why is findOne on a single document not found in miniMongo when it does exist?

This is such a weird problem. I think it has to do with how I am querying the document. It seems like the Meteor API has changed to query documents but the docs on the website are the same.
Here is a document in the database:
meteor:PRIMARY> db.studies.findOne()
{ "_id" : ObjectId("56c12e6537014a66b16771e7"), "name" : "Study 1" }
I have subscribed to get all documents and here is what I am trying in the console to get the documents.
var study = Studies.findOne() // This works.
It returns:
_id: MongoID.ObjectID
_str: "56c12e6537014a66b16771e7"
name: 'Study 1'
I just started a new Meteor project with React. I see that my collection is returning _id: MongoId.ObjectId
This is different, I have been using Meteor for awhile with Blaze and I can't remember it returning MongoID.ObjectID instead of just the string
But now if I try and find just that one document, it does not work.
var study = Studies.findOne("56c12e6537014a66b16771e7");
or
var study = Studies.findOne({_id: "56c12e6537014a66b16771e7"});
I am positive I am queuing for the right _id field. I have double checked the ID. Why does trying to find this one document not work?
Please let me know how I can query for a document. Has something changed with Meteor? The documentation still says you can search by id string.
You need to explicitly cast object id string to an ObjectID
var study = Studies.findOne({_id: new Meteor.Collection.ObjectID("56c12e6537014a66b16771e7")});
#Jaco has the correct answer, but I wanted to answer here to clarify what the higher level issue was.
The reason why my find query was not following syntax in Meteor docs is because I inserted the document into MongoDB directly, instead of through the Meteor API.
If you insert the document directly into MongoDB, you have to query the document using the syntax #Jaco mentioned in his answer.
Similar question: Meteor - Find a document from collection via Mongo ObjectId
So instead of changing my query code, I just deleted the document I inserted directly into MongoDB, and inserted a documented using the console in the browser.
Now I can query the document like normal.
So the root of the issue is that if you insert the document directly into MongoDB, you don't get the same type of document as you would if you insert the document using the Meteor API.

Convert string to Mongo ObjectID in Javascript (Meteor)

I have a Meteor application whereby I initially use the _id field from each record in my collection when naming list items in my template.
When get the _id field, I convert it to a string to use in the template.
Now I want to update these records in Mongo and am passing the _id back to a Meteor.method, but these are still in string format and Mongo is expecting an ObjectID(). Is there a simple way to convert this string to the ObjectID()? If not, what alternatives do I have?
Ok, found it! On the /server, within your Meteor method function do this to convert it:
var mid = new Mongo.ObjectID(str_id_sent_to_server);

Need to remove ObjectID() from _id using Meteor

I am retrieving records from Mongo using Meteor. I use the {{_id}} placeholder in my meteor template to use the _id field of the record, but it adds this into my template....
ObjectID("54f27a1adfe0c11c824e04e9")
... and I would like just to have...
54f27a1adfe0c11c824e04e9
How do I do this?
Just add a global helper:
Template.registerHelper('formatId', function(data) {
return (data && data._str) || data;
});
You can also do it like this with ES6 syntax :
Template.registerHelper('formatId', (id) => (id && id._str) || id);
And use it in any template like this:
{{formatId _id}}
This will work for both mongo-style ObjectIds and meteor-style random strings.
Since your documents are using the MongoDB ID format rather than the default Meteor ID format (simply a randomly generated string), you will need to use the MongoDB ObjectId.toString() function described here. But unfortunately, this simply results in your ObjectID being printed out as a string like ObjectID("54f27a1adfe0c11c824e04e9").
I would recommend creating a document ID template helper that cleans your document IDs before including them in the template. Since this issue is most likely related to all of your documents in all of your collections, I would further suggest creating a global template helper. This can be done like so:
Template.registerHelper('cleanDocumentID', function(objectID) {
var objectIdString = objectID.toString();
var cleanedString = objectIDString.slice(objectIDString.indexOf('"') + 1, -2);
return cleanedString;
});
This template helper slices out just the actual object ID string from the string provided by the ObjectId.toString() function. You can use this template helper in your templates like so:
{{cleanDocumentID _id}}
I know that this is a lot messier than simply using the document ID in the template like {{_id}}, but it is necessary due to the fact that your documents have the MongoDB ObjectID-type document ID rather than the simple randomly generated string as used by Meteor by default.
If you would like to learn more about how to set your MongoDB collections to use randomly generated strings for document IDs and avoid this mess, check out this.
In Blaze templates, just add this {{_id.valueOf}}, and you will have a string value of the actual Object Id.
mongo is capable of storing many types including uuids and custom ones. the field is usually a self-describing object, comprised of the type and the id.
your record is using the default mongo format evidenced by the "ObjectId" prefix.
try ObjectId("507f191e810c19729de860ea").str

Meteor - Find a document from collection via Mongo ObjectId

If you create a Mongo document directly inside Mongo and want to access this same document via Meteor, what is the best way to accomplish this task?
I am getting undefined result when I attempt to access.
If you create a new document from Meteor it does not prefix the id with ObjectId("").
Any help would be greatly appreciated.
I want to simply find exact document by exact ObjectId.
Use Meteor.Collection.ObjectID:
var oid = new Meteor.Collection.ObjectID("a86ce44f9a46b99bca1be7a9");
var doc = SomeCollection.findOne(oid);
See the options for how unique IDs in collections are generated. However, it's general practice in Meteor to use the string approach because clients can then generate unique IDs reliably.