Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Model.find().toArray() claiming to not have .toArray() method

I am very new to Node.js and MongoDB and am trying to piece together my own blogging application. I have a problem trying to query through my 'Blog' model for ones with a specific username. When I try to run:

var userBlogs = function(username) {
  ub = Blog.find({author: username}).toArray();
  ub = ub.reverse();
};

I get an error:

TypeError: Object #<Query> has no method 'toArray'

I know globals are bad but I've just been trying to get it to work. The Mongo documentation claims that a cursor is returned which can have the toArray() method called on it. I have no idea why it won't work.

Here is my schema/model creation:

var blogSchema = mongoose.Schema({
  title: {type:String, required: true},
  author: String,
  content: {type:String, required: true},
  timestamp: String
});
var Blog = mongoose.model('Blog', blogSchema);

Here are the /login and /readblog requests

app.get('/readblog', ensureAuthenticated, function(req, res) {
  res.render('readblog', {user: req.user, blogs: ub})
})

app.get('/login', function(req, res){
  res.render('login', { user: req.user, message: req.session.messages });
});

app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/login'}),
  function(req, res) {
    userBlogs(req.user.username);
    res.redirect('/');
  });
});

The end result is supposed to work with this Jade:

extends layout

block content
    if blogs
        for blog in blogs
            h2= blog[title]
            h4= blog[author]
            p= blog[content]
            h4= blog[timestamp]
    a(href="/writeblog") Write a new blog

How can I get the query to output an array, or even work as an object?

like image 711
Rorschach120 Avatar asked Dec 31 '13 13:12

Rorschach120


3 Answers

The toArray function exists on the Cursor class from the Native MongoDB NodeJS driver (reference). The find method in MongooseJS returns a Query object (reference). There are a few ways you can do searches and return results.

As there are no synchronous calls in the NodeJS driver for MongoDB, you'll need to use an asynchronous pattern in all cases. Examples for MongoDB, which are often in JavaScript using the MongoDB Console imply that the native driver also supports similar functionality, which it does not.

var userBlogs = function(username, callback) {
    Blog.find().where("author", username).
          exec(function(err, blogs) {
             // docs contains an array of MongooseJS Documents
             // so you can return that...
             // reverse does an in-place modification, so there's no reason
             // to assign to something else ...
             blogs.reverse();
             callback(err, blogs);
          });
};

Then, to call it:

userBlogs(req.user.username, function(err, blogs) {
    if (err) { 
       /* panic! there was an error fetching the list of blogs */
       return;
    }
    // do something with the blogs here ...
    res.redirect('/');
});

You could also do sorting on a field (like a blog post date for example):

Blog.find().where("author", username).
   sort("-postDate").exec(/* your callback function */);

The above code would sort in descending order based on a field called postDate (alternate syntax: sort({ postDate: -1}).

like image 54
WiredPrairie Avatar answered Oct 16 '22 20:10

WiredPrairie


Try something along the lines of:

Blog.find({}).lean().exec(function (err, blogs) {
  // ... do something awesome... 
} 
like image 3
user3302709 Avatar answered Oct 16 '22 18:10

user3302709


You should utilize the callback of find:

var userBlogs = function(username, next) {
    Blog.find({author: username}, function(err, blogs) {
        if (err) {
            ...
        } else {
            next(blogs)
        }
    })
}

Now you can get your blogs calling this function:

userBlogs(username, function(blogs) {
   ...
})
like image 2
Mattias Farnemyhr Avatar answered Oct 16 '22 19:10

Mattias Farnemyhr