Does findOne actually work?


#1

This is really driving me nuts. I am simply trying to get a single instance of an object to get its name.

As you can see, I’m peppering with console.logs. The id is value. The “Resorts” collection is valid; I can look at it in the debugger and the data I expect is there, with the key I expect.

“theResort” is not defined…always. Have tried many things.

If there’s anything you can see here that doesn’t look right, please let me know. I’ve struggled with this for hours. Such a simple thing…becoming convinced that the environment is busted.

Template.night.helpers({

resortName: function() {
console.log(“1”);
var id = this.resortId;
console.log(id);
console.log('Resorts: ');
console.log(Resorts);
theResort = Resorts.findOne( { _id : id });
console.log(“2”);
console.log(theResort);
console.log(“3”);

return theResort.name;

},


#2

If you manually run that query in the browser console, Resorts.findOne( { _id : 'xxxxIDHERExxxxx' });
Do you get the correct document returned?


#3

The problem might be a timing issue caused by the template asking the helper for its data before that data has been loaded by the subscription.

My suggestion is to do something like this in the template:
{{#if Template.subscriptionsReady}} run code that is using helper {{else}} display loading spinner here {{/if}}

This assumes that you are using template-level subscriptions such as this.subscribe('mySubscription') inside your template’s onCreated or onRendered callbacks. You can also access whether the subscription is ready (whether all template-level subscription-data has been loaded) within the helper itself with Template.instance().subscriptionsReady().


#4

Right–and that’s something else I’m confused about.

I won’t work if I use the literal string, but if I wrap it like this then, yes, I get the correct object.

Resorts.findOne( { _id: new Mongo.Collection.ObjectID(“5725741fffb339e7b710d2c7”) } )

I know the object is on the client when the page renders, because this list of objects is used in another control and works fine.


#5

I tried this, and it seems to think the subscription is ready; runs the code as normal.

There is a subscription that gets a full list of “resorts.” The resorts are getting to the client because they are used in a different list. My subscribe is in another helper/template, but I added it to this helper as well; no difference.

This is really frustrating because this is a simple building block that should be trivial. I am displaying a list of “nights” each of which contain an id for a resort…basically a foreign key reference. So, I just need to access that other ‘table’ and get the name. I’ve spent more time debugging this than anything I’ve done in meteor so far.


#6

That is strange, I’ve never had that before.
That would be the reason your findOne queries aren’t working, because thats a direct translation of what you’re helper function is doing. In your helper function, try wrapping the id variable with the wrapper you use in the console…

Why that is happening I have no idea… are you manually creating the _id values when inserting into the database?


#7

I’ve had tried wrapping the object’s ID various ways in the template with no results. The thing is, it already shows as an ObjectID in the console.log. It’s not real clear how it wants to be wrapped.

I’m letting mongo create the _id.

Quite honestly, I may try recreating the project entirely and move code over. I have a feeling something is screwed up. I’ve also started with samples from various tutorials, and it’s looking like there are differences because things have changed with meteor itself.

Hope I can get past this. It seems like this framework can be marvelously productive, and I want to crank out a fairly simple app with it.


#8

if you do not care about privacy of the app/code upload it on a github repo and I will have a look at it


#9

It sounds like you’re using ObjectID values for the documents’ _id field instead of string values. Is that what’s happening?

meteor add babrahams:constellation, then take a screenshot of one of the Resorts documents that is in the browser cache (via the Constellation UI) and post the image here. After that, it should be pretty clear what’s going on.


#10

Day job has been holding me up here…

Well, I thought I’d write a completely new app–figured if I dumbed it down quite a lot with some generic documents, I’d be able to get it working and then be able to work forward. But I’m having the same problem.

I am creating “Thing”. There is a lookup table of “ThingTypes”. Thing stores a thingType, which an objectID for the ThingsTypes table.

Here’s a thing (in firefox):
{
Object { _id=“E6x74pyNdLXnziuqa”, thingType=“ObjectID(“57296bd527ed9cbf5f4fa30f”)”, name=“Four”, more…}
}

And ThingsTypes (in firefox):

Object { _id=ObjectID(“57296bc027ed9cbf5f4fa30c”), name=“One”}
Object { _id=ObjectID(“57296bcc27ed9cbf5f4fa30d”), name=“Two”}
Object { _id=ObjectID(“57296bd127ed9cbf5f4fa30e”), name=“Three”}
Object { _id=ObjectID(“57296bd527ed9cbf5f4fa30f”), name=“Four”}

So, in the firebug console, I do this

id = Things.findOne().thingType

this gives me:

“ObjectID(“57296bd527ed9cbf5f4fa30f”)”

Now when I do:

ThingTypes.findOne(id)

That gives me “undefined.” I would expect that to give me a “ThingType.”

ThingTypes.findOne( { _id: id } )

also gives me undefined.
I could post to github, but I’m not really current on how to use git.


#11

just open a github account and create a repository, might have to dwonload git cli tool…its all pretty straightforward though…I think it will be hard to solve without putting the app on github


#12

How are you putting documents into the database?

If you’re using MongoDB itself (or possibly some other non-Meteor application) and you are not specifying the id on insert (like insert({name: 'bob', age: 23})) then you will end up with MongoDB ids, which are objects. Within Meteor, you will get a string _id if you do not specify the _id.

If you do specifiy the _id, then you have two choices: a string or a MongoDB object id. Meteor supports both, but as you have found you need to explicitly use new Mongo.ObjectID if you have (or want) MongoDB object ids.

By default, Meteor uses strings for _id. If you are trying to mix the two in the same collection, they are largely incompatible with each other. By using this form:

Resorts.findOne( { _id: new Mongo.ObjectID("5725741fffb339e7b710d2c7") } )

You are forcing Meteor to match using MongoDB object ids, rather than strings.

By using either of these forms:

Resorts.findOne( { _id: "5725741fffb339e7b710d2c7" } )
Resorts.findOne("5725741fffb339e7b710d2c7")

You are specifying strings.


#13

Why are you mixing string _id values and Mongo object _id values in the same app?

Your Things collection has documents with string _id values like _id="E6x74pyNdLXnziuqa", whereas your ThingTypes collection has documents with Mongo object _id values like _id=ObjectID("57296bd527ed9cbf5f4fa30f").

I’d recommend just using string _id values for all documents in all collections. Meteor uses string _id values out of the box and, as you can see from your example above, they work as expected. (Things.findOne() returned a document, while ThingTypes.findOne( { _id: id } ) didn’t.)

EDIT: @robfallows – you beat me to it! (And your answer was better. :slight_smile:)


#14

:smile: It’s been a while since I did that!


#15

"Why are you mixing string _id values and Mongo object _id values in the same app?’ – that would be because I had no idea or expectation that meteor would have a limitation on mongo’s id generation like that!

I have my mini-app working. I had to push my “ThingTypes” into mongo from javascript, and eventually got it all pieced together.

This seems like an odd limitation. I would thing it’s likely one would want to interact with the mongo db with other apps and be able to use it’s native id generation. For example, maybe there’s a separate python application that populates the “ThingTypes”. As it is, it looks like you’d have to explicitly generate every id–other apps would have to know to do that. How do you deal with this in your apps?

Anyway, if I encountered anything like this in docs or tutorials, I may well have glossed over it because I wouldn’t have expected this.

Thank you so much for all the help. I don’t think I would have figured this out without this forum because it just wasn’t something I was expecting.


#16

Oh, and backing up: I was creating the ThingTypes directly in mongo db. Probably should have noticed some id’s were wrapped in “ObjectID” and others not…


#17

I am having a similar problem with findOne().fetch(). I get

Uncaught TypeError: Cannot read property 'fetch' of undefined

However, if I do ColName.findOne() only it doesn’t produce any errors, but with Meteor 1.3 + React I need to apply fetch(). So what would be the solution?


#18

You don’t need to run fetch on findOne. FindOne returns an object. Find() returns a cursor which needs to be fetched.


#19

cstart - Thanks. I discovered a couple of minutes before you pointed that out.