Struggling with .find() vs. .findOne() in my Meteor app - meteor

I realize that this might be very close to other posts, but I just can't get this to stick in my head! :( I need some help in trying to understand how to use .find() or should I be using .findOne()? (so confused) for a collection of mine.
Goal:
I want to get all of the documents out of the People collection and then for each document I want to create a new <option> where the .name is put in for text and the collection ._id is the value.
Here's some code:
The Collection results from Mongo
db.people.find()
{ "_id" : "1", "name" : "John" }
{ "_id" : "2", "name" : "Mike" }
{ "_id" : "3", "name" : "George" }
{ "_id" : "4", "name" : "Jane" }
My Template Helper :
Template.view_Admin_Staff.people = function() {
console.log( 'people : ', People.find() );
return People.find();
};
My Template :
<select id="ddStaffID" name="staff">
<option value="">-- Select One --</option>
{{#each people}}
<option value="{{_id}}">{{name}}</option>
{{/each}}
</select>
My console.log found in the Helper returns undefined. What in the world am I missing?

I am going to assume that your collection is People = new Meteor.Collectin('people'); And your template name for in the html is
When you did the console log in your template helper, you are logging the cursor itself, not the documents. You can find out more about cursor at (https://www.eventedmind.com/tracks/feed-archive/how-do-client-cursors-work).
To see are you returning the correct data, you could .fetch method on a cursor. Fetch will return an array of objects based on your query. In your case, the query is empty, the fetch method should return everything that is available in the client's db.
To answer your question in the title. both find and findOne are methods available on the Collection object.
find return a cursor. findOne return AN object, if there is a record matched to your query.

Bloody-h3ll! Warning to all us n00bs out there...one must subscribe to your publications in order for one to see and work with your publications. sigh
The code in my initial post is working as expected. I just simply forgot to subscribe to my exposing data in my publication in my client-side route. </foreheadSlap> I'm new enough to have doubted my query skills and didn't even thing to troubleshoot any further back in the code. Thank you #Bozhao and #DavidWeldon for your quick replies.

Related

Meteor: md-autocomplete with reactive helper

When I use md-autocomplete, the filter is applied to the second last keypress and not to the current one. I tried different options for filtering but I'm stuck and don't know how to integrate my Meteor collection with md-autocomplete.
In my controller component, I have the filter logic implemented like this:
this.searchText = '';
this.subscribe('people');
this.helpers({
people() {
return People.find({
name: {
$regex: `${this.getReactively('searchText')}.*`,
$options: 'i'
}
});
}
});
my template looks this way:
<md-autocomplete
md-selected-item="ctrl.selectedItem"
md-search-text="ctrl.searchText"
md-items="person in ctrl.people"
md-item-text="person.name"
md-min-length="0"
placeholder="Who should be selected?">
<md-item-template>
<span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{person.name}}</span>
</md-item-template>
<md-not-found>
Nobody found matching "{{ctrl.searchText}}".
</md-not-found>
</md-autocomplete>
The filter works beside the problem, that the last key ob my searchText is not applied to filter the list.
Example: I have the people "Till", "Tony" and "Andy" in my collection. when I type "T", nothing is filtered out at all, but the T from Till and Tony is highlighted correctly on my list.
When I type "Ti", Till and Tony stay in the list and Andy is filtered out. The "Ti" of Till is highlighted. So the highlight works as expected, but the filter does not apply to the last letter I typed.
I would be glad for some hints, how to apply my searchText correctly to md-autocomplete. I was searching for my mistake for hours now, without success.

meteor how to define class level methods?

I have a collection called "Articles". Each article has a category. I would like to have a global variable being an array with each distinct category value in my Articles collection.
I tried to do it this way:
/models/article.coffee:
#Articles = new Meteor.Collection "articles"
Articles.categories = ->
Meteor.call "articleCategories", (e, r) ->
unless e
return r
/server/article_server.coffee:
Meteor.methods
articleCategories: ->
categories = _.uniq(Articles.find({}, {sort: {category: 1}, fields:
{category: true}}).fetch().map (x) ->
x.category
, true)
return categories
This doesn't work. The result is "undefined" when I call Articles.categories() from the console.
What am I doing wrong?
EDIT:
I want to do this because I want my article categories to be available everywhere in the website.
As Articles collection will not be published on every pages, I tought, I could just generate an array server side and pass it over to the client.
But maybe it's not a good idea...
A Meteor.method will always return undefined on the client (unless a simulation/stub exists and it's called within another parent method) so this behavior is expected.
I'm not sure why you'd need a Meteor.method in this particular use case though, can't you just copy your method code inside your class method ?
EDIT :
To accomplish what you want to do, I'd suggest changing your model to create a Categories collection filled with every possible categories and just publish the entire content to the client.
Then just use a foreign key in your Articles collection.
An added benefit will be that your categories access client side will be reactive, contrary to using a Meteor.method.
Whether it's Telescope or even Wordpress I think this schema is very popular.
Take a look at this package:
https://github.com/dburles/meteor-collection-helpers
And add something like this (I wrote in javascript) in your model:
Articles.helpers({
categories: function(){
return _.uniq(
_.pluck(Articles.find({}, {sort: {category: 1}, fields:
{category: true}}).fetch(), 'category'),
true
);
}
});

Mongo's elemMatch with meteor publish composite

I have a Mongo collection that looks similar to the below example, I am using meteor-publish-composite, https://atmospherejs.com/reywood/publish-composite to publish documents to the client. I know with Mongo I can do the following to return specific items within the authors array.
db.books.find({"authors.authorSlug": "author-1}, {authors: {$elemMatch: { authorSlug: "author-1"}});
When I try to achieve the same thing using meteor-publish-composite, this does not seem to work as it returns the entire the authors' array, my code is as below.
Books.find({"authors.authorSlug": slug}, {authors: {$elemMatch:{authorSlug: slug}}});
Is this even possible to achieve with publish-composite?
{
"title" : "Book1",
"authors" : [
{
"name" : "Author 1",
"authorSlug": "author-1"
},
{
"name" : "Author 2",
"slug" : "author-2"
},
],
"slug" : "book1"
}
You only use publish-composite when you are trying to join 2 or more related collections into a single reactive subscription. You simply need a standard publish/subscribe for your collection - and you say you have working code so I don't see what your problem is! Or are you trying to get at your books data in addition to other data around it?

Removing the Last Item From a List created By .push()

I am having trouble deleting a single item from a list. I want to delete the 'oldest' item, and these have been added via the .push() method. It seemed pretty straightforward to do this but I am having issues. For my data structure, please see below. I am sure I am just doing something dumb as this must be a common use-case.
Any ideas/feedback would be greatly appreciated.
Code:
firebase.child('articlesList').orderByChild('site').equalTo('SciShow').limitToFirst(1).once('value', function(snapshot){
// This was one try, This seems to remove the entire articleList
snapshot.ref().remove();
// I have also tried this, and this seems to do nothing at all
snapshot.forEach(function(dataSnapshot){
dataSnapshot.ref().remove();
});
});
Data Structure:
"articlesList" : {
"-Jc16JziK668LV-Sno0s" : {
"id" : "http://gdata.youtube.com/feeds/api/videos/c8UpIJIVV4E",
"index" : "SciShow",
"link" : "http://www.youtube.com/watch?v=c8UpIJIVV4E&feature=youtube_gdata",
"site" : "SciShow",
"title" : "Why Isn't \"Zero G\" the Same as \"Zero Gravity\"?"
},
"-Jc16Jzkn6q41qzWw3DA" : {
"id" : "http://gdata.youtube.com/feeds/api/videos/Wi9i8ULtk4s",
"index" : "SciShow",
"link" : "http://www.youtube.com/watch?v=Wi9i8ULtk4s&feature=youtube_gdata",
"site" : "SciShow",
"title" : "The Truth About Asparagus and Your Pee"
},
"-Jc16Jzkn6q41qzWw3DB" : {
"id" : "http://gdata.youtube.com/feeds/api/videos/J7IvxfcOkmM",
"index" : "SciShow",
"link" : "http://www.youtube.com/watch?v=J7IvxfcOkmM&feature=youtube_gdata",
"site" : "SciShow",
"title" : "Hottest Year Ever, and Amazing Gecko-Man Getup!"
},
The folks over at Firebase answered this for me on their Google Group. I figured I would post for others to use.
= = =
Hey Ryan,
You are close! Instead of using the value event, you want to use the child_added event. The value event will get fired once with all the data at your /articlesList/ node. That is why you are seeing it delete the whole list. If you use the child_added event, it will fire for each child. Or, if you limit it like you did, it will only fire for a subset of children. One other thing to change is to use limitToLast(1) instead of limitToFirst(1) to get the last child.
Here's the code:
firebase.child('articlesList').orderByChild('site').equalTo('SciShow').limitToLast(1).once('child_added', function(snapshot){
snapshot.ref().remove();
});
Jacob

Meteor Publishing partial collection

I want to publish a collection to the user that the user 'owns'
Meteor.publish('test', function(){ return questiondummy.find({'author':'Jaspermid'});
});
And the subscribe to it with
Meteor.subscribe("test");
Unfortunately this does not work. I can find the collection within mongodb database with the exact username
{ "questionnumber" : 10, "user" : "Jaspermid", "timestamp" : 1407063133137, "answerarray" : [ "1", "2", "3", "4" ], "_id" : "fDcfnenhNsZNAmsze" }
1. Does anyone know why I cannot see this collection on the client side
2. How and where to incorporate (Meteor.user().username to publish to the current user only?
Thank you in advance
You have access to the current user's _id from within the publish function through this.userId. You can use that to find the username.
http://docs.meteor.com/#publish_userId
Meteor.publish('test', function(){
var user = Meteor.users.findOne(this.userId);
if (user)
return questiondummy.find({user: user.username});
this.ready();
});
this.ready() tells the client that the subscription is ready even though you haven't sent any data (as in when the user is not logged in).
The selector to find should be {'user':'Jaspermid'}, and not {'author':'Jaspermid'}.
Instead of the selector {'user':'Jaspermid'}, use {'user': Meteor.user().username}
EDIT
Oups, Meteor.user() can be used "Anywhere but publish functions". My mistake.

Resources