Meteor mongo get and set value - mongodb

I am pretty new to Meteor and I'm just toying around to explore it at the moment.
I've got stuck with an issue trying to get and set a value in the mongo database, named Persons.
The MongoDB is named Persons and I've inserted two objects:
{name: "abcdef", coming: "false"}
If the user changes the state of a checkbox, that's attached to a name, a function is called that should find the value of the boolean coming.
What I think I got right so far, is that I can set the value like this?
var id = this._id;
Persons.update({_id: id}, {$set: {coming: true}});
But how can i get the value and make comparisons with it?

In meteor you use .find(selector).fetch() or .findOne(selector) on collections to get objects, where selector is a usual mongodb selector or just an id (string). After that you can pick out any fields using the usual . syntax of javascript.
Example:
var obj = Persons.findOne(id);
if (obj) { // the given id was found
console.log(obj.coming);
}

Related

Can't find documents by criteria containing string objectId value

I have a collection list such:
{username: 'somename',
friendId: '57d725d6b8b144044602bf74' <-- This a reference objectId to another doc
}
When I query docs in my collection with criteria {friendId : '57d725d6b8b144044602bf74'} I get no results back .
Any other field query works fine.
I tried to convert the value to ObjectId('57d725d6b8b144044602bf74') even though the value is just a string, still no go.
Why am I failing to search for by that type of string ?
you are trying to achieve 'self-join' in mongoDB and you seems to rely on the _id field generated by mongodb.
i would suggest you to supply custom _ID fields to the document.
eg:
{_id:"alex", name:"alex", friendID:""}
{_id"john", name"john", friendID:"alex"}
and then you can execute your queries with ease on friendID field. Give it a shot and see if this make sense for your requirement.

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

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);

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.

Find the collection name from document._id in meteor (mongodb)

From the looks of the syntax for handling mongodb related things in meteor it seems that you always need to know the collection's name to update, insert, remove or anything to the document.
What I am wondering is if it's possible to get the collection's name from the _id field of a document in meteor.
Meaning if you have a document with the _id equal to TNTco3bHzoSFMXKJT. Now knowing the _id of the document you want to find which collection the document is located in. Is this possible through meteor's implementation of mongodb or vanilla mongodb?
As taken from the official docs:
idGeneration String
The method of generating the _id fields of new documents in this collection. Possible values:
'STRING': random strings
'MONGO': random Meteor.Collection.ObjectID values
The default id generation technique is 'STRING'.
Your best option would be to insert records within a pseudo transaction where the second step is to take the id and collection name to feed it into a reference collection. Then, you can do your lookups from that.
It would be pretty costly, though to construct your find's but might be a pattern worthwhile exploring if you are building an app where your users will be creating arbitrary data patterns.
You could accomplish this by doing a findOne on all of the collections:
var collectionById = function(id) {
return _.find(_.keys(this), function(name) {
if (this[name] instanceof Meteor.Collection) {
if (this[name].findOne(id)) {
return true;
}
}
});
};
I tested this on both the client and the server and it seemed to work when run in the global context.

How do you access attributes of an object queried from Mongo in Meteor

I'm pretty new to mongo in the Meteor.js framework. Here, I've queried a MongoDB object using it's ID. I'm trying to access an attribute "mana" but it returns me undefined.
var skill = Skills.find({_id:Session.get("selected_skill")});
alert(skill);//This returns me "undefined"
Skills.update(Session.get("selected_skill"), {$inc: {mana: 1}});
Could you enlighten me on the requirements of accessing attributes in mongo for meteor? Thanks
find method returns a cursor, not object nor array. To access object, you need to either fetch it from the cursor
var skill = Skills.find(Session.get('selected_skill')).fetch()[0];
or get it directly with findOne:
var skill = Skills.findOne(Session.get('selected_skill'));
Then you may use it just as any other js object:
console.log(skill.mana);
skill._cache = {cooldown: true};
Keep in mind that on client-side, collection methods like find are non-blocking. They return whatever Meteor has in cache, not necessarily what is in the server-side db. That's why you should always use them in a reactive context, or ensure that all data has been fetched before execution (don't worry about the latter until you're fluent with Meteor, start with the first way).
Also, you need to keep in mind that because of this, findOne and find.fetch may return null / empty array, even when the corresponding element is in db (but hasn't been yet cached). If you don't take that into account in your reactive functions, you'll run into errors.
Template.article.slug = function() {
var article = Articles.findOne(current_article);
if(!article) return '';
return slugify(article.title);
};
If we didn't escape from the function with if(!article), the expression article.title would raise an error in the first computation, as article would be undefined (assuming it wasn't cached earlier).
When you want to update the database from client side, you can alter only one item by a time, and you must refer to the item by its _id. This is due to security reasons. Your line for this was ok:
Skills.update(Session.get('selected_skill'), {$inc: {mana: 1}});
alert() is a function that returns undefined no matter what you feed it.
alert(42); // -> undefined
Generally, it's far better to debug with console.log than with alert.