4

I am new in Node.js so sorry if this is really stupid question but however I try I can't find the answer.

I have some simple code:

var express = require("express");
var mongoose = require("mongoose");
var cors = require("cors");

mongoose.connect('mongodb://localhost/simple')

var personSchema = {
    firstName:String,
    lastName:String,
    email:String
}

var Person = mongoose.model('Person', personSchema, 'people')

var app = express();
app.use(cors());

app.get('/people', function (req, res) {
    Person.find(function (err, doc) {
        res.send(doc);
    })
})

app.get('/people/:id', function (req, res) {
    Person.findById(req.params.id, function (err, doc) {
        res.send(doc);
    })
})
app.listen(3000);

This should return some data I insert to mongo DB, while first one /people/ return everything correctly (basicly just return dump of DB)

The second one with ID return nothing. I try to debug it and I see that inside of function ID is defined correctly, I also used ID which comes from "people" site (something like : 55e028081181bfdd8a7972d2 ), dispite this fact I am not able to get any answer or error.

Is there a chance someone can advise me where can be a problem?

Andurit
  • 5,612
  • 14
  • 69
  • 121
  • 4
    Did you try to use an ObjectId constructor such as http://stackoverflow.com/questions/6578178/node-js-mongoose-js-string-to-objectid-function ? – mguimard Aug 28 '15 at 09:47
  • I'm not sure how you mean it, did you mean something like: http://pastebin.com/nFxSrZqw If yea unfortunately it doesnt work for me anyway :( – Andurit Aug 28 '15 at 09:57
  • Has that MongoDB been populated with data using your application and through mongoose or through any other method? – Alfonso Presa Aug 28 '15 at 10:11
  • 1
    Kindly share the sample data on how it looks. – Vimalraj Selvam Aug 28 '15 at 10:26
  • 1
    I second that. Show data in your "people" collection. The third argument in the `mongoose.model` call is not needed since that is what it is expecting anyway ( plural of person is people ). – Blakes Seven Aug 28 '15 at 10:27
  • I see you are still online. The other answers ( from those who are being sensible about this ) are dropping like flies. If there is something unclear to you in the response I have given then I suggest you ask whilst I am still here as well. – Blakes Seven Aug 28 '15 at 12:32

2 Answers2

4

It's time this question was debunked, as I myself am very much getting tired of the false responses here.

The code as a unit is fine. The only problems that can be occuring are that you are sending the wrong things or have the wrong collection addressed, as well as one last issue concerning the _id value itself.

You need nothing other than "raw" express and mongoose for this to work, as my listing proves:

var async = require('async'),
    express = require('express'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/simple');

var personSchema = new Schema({
  firstName: String,
  lastName: String,
  email: String
});

var Person = mongoose.model( 'Person', personSchema );

var app = express();

mongoose.connection.on('open',function(err) {

  async.series(
    [
      function(callback) {
        Person.remove({},callback);
      },
      function(callback) {
        Person.create({
          firstName: "John",
          lastName: "Doe",
          email: "john.doe@example.com"
        },callback);
      }
    ],
    function(err,results) {
      if (err) throw err;
      console.log(
        "Created and call in URL: %s",
        results[1]._id
      );

      // setup routes

      app.get('/people', function(req,res) {
        Person.find(function(err,docs) {
          res.send(docs)
        });
      });

      app.get('/people/:id', function(req,res) {
        Person.findById(req.params.id,function(err,doc) {
          res.send(doc);
        });
      });

      app.listen(3000);
      console.log("ready");

    }
  );

});

Which gives output like:

Created and call in URL: 55e0464e66e13f6506e8e38e
ready

So when you call the server on the /people url you get:

[
    {
        "_id":"55e0464e66e13f6506e8e38e",
        "firstName":"John",
        "lastName":"Doe",
        "email":"john.doe@example.com",
        "__v":0
    }
]

As a response.

And when you call with the id as in /people/55e0464e66e13f6506e8e38e then you get:

{
    "_id":"55e0464e66e13f6506e8e38e",
    "firstName":"John",
    "lastName":"Doe",
    "email":"john.doe@example.com",
    "__v":0
}

As expected.

So if your application is not working then you are either not sending in what you think you are, or you actually have a String for the _id value in the collection, or it is completely mismatched in the collection or database name. All urls should work, and if none are working then the latter is the case.

In the case of the _id being a string, then the schema is wrong and needs to be:

var personSchema = new Schema({
  _id: String
  firstName: String,
  lastName: String,
  email: String
},{ "_id": false });

Where most importantly, apart from setting the correct type for the _id field in the schema is also the { "_id": false }.

This is because you need this to tell mongoose to not attempt to parse the "string" into an ObjectId as it always does by default.

Without that setting a "string" will always fail.

But this listing is the proof of what does work, and also the only change really needed if in fact the _id contains a "string" or other type. So if a Number then both set the schema for _id: Number and also { "_id": false } otherwise the same failure reasons occur.


For pure silliness then change my listing to :

var personSchema = new Schema({
  _id: { type: String, default: "55e0464e66e13f6506e8e38e" }, 
  firstName: String,
  lastName: String,
  email: String
},{ "_id": false });

And watch it work every time also.

And please also remove the { "_id": false } and watch it fail so it becomes clear why this is required when the _id type is meant to be overridden.

Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
  • You are naturally right, the body-parser helped with put and post requests, where the json data was sent as req.body. – Pavel Gatnar Aug 28 '15 at 11:52
  • @PavelGatnar Well since POST data is in the "body" then you would need something here, or manually handle. This request is in the URL and therefore accessible by `req.params` all of the time. The code is here for people to reproduce. The reasons for possible failure ( all of them ) are also listed here. – Blakes Seven Aug 28 '15 at 11:54
  • As you expect this return me the right value when I open /people/ but I am a bit comfuse of this code. Do I understand it correctly that you remove everything after that, add one single line? because if yea it's not helping. I need to /people/ return all values and /people/id/ return just value with ID: ) – Andurit Aug 28 '15 at 12:45
  • @Andurit I submit this as a "self contained example" for other people and yourself to run for themselves "over and over again" with the same reproducible results. Therefore the things happing before I start to define routes are generally not applicable to your own code. But the principles are. I am basically creating something with a structure I expect, and then issuing exactly the same method calls as you are. Therefore as I state, there is no problem with the code you have. Just that the inputs or data does not match what you are asking and your expectation. – Blakes Seven Aug 28 '15 at 12:52
  • Thank you for explain, is there a chance we can discuss a bit about this on chat? I would like to know few more details :) p.s. Marking your answer as correct – Andurit Aug 28 '15 at 13:11
  • @Andurit Sure. [Join](https://chat.stackoverflow.com/rooms/88200/mongoose-find-by-id-problem) – Blakes Seven Aug 28 '15 at 13:20
-1

If you have populated your database from outside mongoose, there's a chance you have changed the type of the _id property. If that's the case try adding _id to your schemma as follows:

var personSchema = {
    firstName:String,
    lastName:String,
    email:String,
    _id:String
}
Alfonso Presa
  • 1,024
  • 7
  • 11
  • Umm. `.findById()` is a mongoose method. And the `Person` model has been clearly defined. – Blakes Seven Aug 28 '15 at 10:23
  • @BlakesSeven Yes, according to the opening question: *This should return some data I insert to mongo DB* which suggests that the data and the Schema are created manually or by some other system. – Alfonso Presa Aug 28 '15 at 10:25
  • But your "answer"? Does not even have anything to do with that. I was just warning you before I and others downvote this. Oh. And mongoose treats "id" and "_id" as the same thing. So you clearly do not know the material and are just searching the internet. Most people can do that. Just so you know why the downvotes are happening. – Blakes Seven Aug 28 '15 at 10:29
  • @BlakesSeven. I'm answering to the question on how to read preexisting documents from MongoDB with mongoose, as that's what I understand he is asking about. I might be wrong, but definitely the code he is sharing is read only, so my guess is that his current documents doesn't have an `_id` property. – Alfonso Presa Aug 28 '15 at 10:34
  • @BlakesSeven Just so you (and everyone else) know I've executed his code locally against my MongoLabs account, adding a POST endpoint to create new entries before posting my answer. It's working perfectly fine – Alfonso Presa Aug 28 '15 at 10:46
  • Just so you and everyone else knows. Now please change your code to use `.findById()` as a method and please share with us all why it fails. Haninging on your expert feedback. – Blakes Seven Aug 28 '15 at 10:48
  • @BlakesSeven you're right. I though he might have overcome the _id creating but that's not possible. What might have happened is that he has bulk imported the data and thus the type of the _id has changed to a different type (like string probably) making mongoose fail. I've replicated it locally. – Alfonso Presa Aug 28 '15 at 11:07
  • Also noticed you did not share the results for your `.findById()` not working claims and just chose to completely re-write your answer instead. It's okay as we can still see the revision history. And yes I am right. And about everything I have said to you here. You clearly do not undertand the topic, so you are not the person to submit an answer. – Blakes Seven Aug 28 '15 at 11:11
  • @BlakesSeven I told you in the previous comment. You were right about the impossibility of having `findById`not working because of having a different id field (as it's mandatory for MongoDB to have `_id`). About the `"_id":String` it does make a difference. Try it yourself: create a document specifying a fixed string id in mongolabs console `{"_id":"myownid"}`, then try to query it with and without specifying the _id in the schema with `findById`. – Alfonso Presa Aug 28 '15 at 11:19