Mongoose: utilize populate for fetching records; if not, return an array of records

Learning MeanJS and encountering Mongoose issues. Two models are in question:

CategorySchema: 
- name: String, default:'', required: 'Please fill Category name', trim: true
- slug: String, default:'', trim: true, unique: true
- created: Date, default: Date.now
- user: Schema.ObjectId, ref: 'User'
- articles: [Schema.ObjectId, ref: 'Article']

ArticleSchema:
- created: Date, default: Date.now
- category: Schema.ObjectId, ref: 'Category'
- title: String, default:'', trim: true, required: 'Title cannot be blank'
- slug: String, default:'', trim: true, unique: true
- content: String, default:'', trim: true
- user: Schema.ObjectId, ref: 'User'

Saving articles with the following function:

exports.create = function(req, res) {
    var article = new Article(req.body);
    article.user = req.user;

    article.save(function(err) {
        if (err) {
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        } else {
            Category.findById(article.category).exec(function(err, category) {
                category.articles.push(article.category);
                category.save(function(err, category) {
                    if (err) {
                        return res.status(400).send({
                            message: errorHandler.getErrorMessage(err)
                        });
                    } else {
                        res.json(article);
                    }
                });
            });

        }
    });
};

All is saving correctly and the object structure appears as follows:

{
    "_id" : ObjectId("55b73bf97aa70c2c083655b0"),
    "user" : ObjectId("55b115f35c7a03cc0e59d821"),
    "articles" : [ 
        ObjectId("55b73c017aa70c2c083655b2"), 
        ObjectId("55b73ee20bab5e8c0c7eadca")
    ],
    "created" : ISODate("2015-07-28T08:23:21.562Z"),
    "slug" : "motocycles",
    "name" : "Motocycles",
    "__v" : 2
}

However, upon attempting to retrieve data using .populate('articles'), unexpected behavior occurs:

exports.list = function(req, res) {
    Category.find().sort('-created').populate('user', 'displayName').populate('articles').exec(function(err, categories) {
        if (err) {
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        } else {
            res.jsonp(categories);
        }
    });
};

The length now returns 0, ObjectIds disappear, and access to article properties is lost. This occurrence raises questions on why this might be happening.

Additional edit:

mongoose.model('Article', ArticleSchema);
mongoose.model('Category', CategorySchema);

Answer №1

After some troubleshooting, it became clear that the issue lay within the create function. By making a few adjustments, I was able to get it up and running smoothly:

exports.create = function(req, res) {
  var article = new Article(req.body);
  article.user = req.user;

  article.save(function(err, savedArticle) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      Category.findById(article.category).exec(function (err, category) {
        category.articles.push(savedArticle);
        category.markModified('articles');

        category.save(function (err, category) {
          if (err) {
            return res.status(400).send({
              message: errorHandler.getErrorMessage(err)
            });
          } else {
            res.json(savedArticle);
          }
        });
      });
    }
  });
};

I found it interesting that even though the Category object contained correct Article ObjectId's, the functionality was still not working as expected.

Answer №2

Understanding the nuances of variables, schema instances, and using ObjectId can be a bit tricky (especially with the not-so-clear mongoose documentation).

var categorySchema = new mongoose.Schema({
    name: {
        type: String,
        required: 'Please fill Category name',
        trim: true
    },
    slug: {
        type: String,
        trim: true,
        unique: true
    },
    created: {
        type: Date,
        default: Date.now
    },
    user: {
        type: mongoose.Types.Schema.ObjectId,
        ref: 'User'
    },
    articles: [{
        type: mongoose.Types.Schema.ObjectId,
        ref: 'Article'
    }]
});

var articleSchema = new mongoose.Schema({
    created: {
        type: Date,
        default: Date.now
    },
    category: {
        type: mongoose.Types.Schema.ObjectId,
        ref: 'Category'
    },
    title: {
        type: String,
        trim: true,
        required: 'Title cannot be blank'
    },
    slug: {
        type: String,
        trim: true,
        unique: true
    },
    content: {
        type: String,
        trim: true
    },
    user: {
        type: mongoose.Types.Schema.ObjectId,
        ref: 'User'
    }
});

When working with an MV* pattern and separate files for each concern, make sure to export your models like this:

exports.method = mongoose.model('Category',categorySchema);
exports.otherMethod = mongoose.model('Article',articleSchema);

The use of .method and .otherMethod is common in Node.js, but it might differ in Express or other frameworks.

Finally, remember to name and require this file using its path.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

User currently signed in: What specific information should be transmitted to the web browser?

Experience: Currently utilizing the MEAN stack for a web application and still in the learning process. The Concern: I am facing some confusion regarding a particular aspect. For instance, if a user is logged in (using Passport.js), I can access their inf ...

Is it possible to use a variable in JSX within a map function to modify inline CSS styles?

I have a map function that loops through an array and generates divs on the DOM for each color item. The array consists of hex values representing different colors (e.g. #1a703f). The goal is to set the background of each div to match the corresponding co ...

Form calculation

An issue has arisen with my calculating form for a client where an incorrect amount is displayed when 0.93 is entered into the percentage box. Original calculation: 10 x 10 x 15 x 0.93 = 13.95 Corrected calculation: 10 x 10 x 15 x 0.93 = 1.395 I am seek ...

Analyzing refined information using D3

After loading data, I implemented a filter feature using checkboxes. Every time the checkbox is updated, the date field in the data needs to be parsed. The script below achieves this successfully on the first click but encounters an error on subsequent c ...

JavaScript/ajax HTTP request is being made, but encountering an issue with 'Access-Control-Allow-Origin'

Currently, I am using asp.net c# to retrieve the status of an application running on a client's server via port 9192. To accomplish this, I have implemented the following ajax get call. All my clients are connected to the server through VPN, so I am u ...

Loop through a collection of unique identifiers for documents and establish event listeners in Firestore

Within my Vuex store, there is an action designed to retrieve a list of uids for followed users from the current user's Firestore UserDataCollection document. The action then processes each uid to extract data that will be displayed on the UI. While t ...

Using ExpressJS and AngularJS to Convert JSON Object into a String

Struggling with a seemingly simple issue despite hours of searching on Stackoverflow. Using Sir Trevor with MEANJS. Sir Trevor saves content as a JSON String in the 'Content' field, set as an 'Object' type in a Mongoose schema. Creati ...

Click event triggering smooth scrolling

I am currently working on implementing a smooth scrolling effect using the React JavaScript library without relying on jQuery. My goal is to ensure that when a user clicks on a link, they are directed to the specific section of the page seamlessly. The f ...

Showing VUE Content Delivery Network

Unable to render v-for with CDN in Vue.js const Gallery = { template: '{{$t('gallery')}} <img :class="[[item.class]]" v-for="(item, index) in carousel" :src="[[item.img]]" alt="img" />' } c ...

Retrieving input field values in JS/Ajax without needing to refresh the page or click a button

Currently, I have set up a JavaScript function that submits data without refreshing the page or requiring a button click. The input field is located within tab #2 and triggers the JS function when the user stops typing. However, the issue arises when the ...

I encountered difficulties trying to retrieve data from MongoDB using a localhost URL with MongoJS library

This is the sample tasks.js code that I am currently trying to execute: /*jslint node:true*/ var express = require('express'); var router = express.Router(); var mongojs = require('mongojs'); var db = mongojs('mongodb://localhos ...

Error compiling template due to custom component issue

Can you help me troubleshoot my custom component? I'm trying to create a setup with: label input Why am I seeing the error message "idfor is undefined"? And what's causing the issue with labeltext? An unexpected identifier was found in the ...

Fetch data dynamically with jQuery AJAX

I am working on a jQuery Ajax form submission to a PHP page with the goal of dynamically returning values instead of all at once. For instance, in my jQuery code: jQuery.ajax({ type: "POST", url: "$PathToActions/Accounts.php", dataType: ...

To link various JavaScript files in WordPress

When working on a project in WP 4.2, I am currently adding JavaScript files like this: add_action('wp_print_scripts', array(&$this, 'admin_load_scripts')); ... function admin_load_scripts() { wp_register_script('BackendAr ...

Change the destination of an iFrame upon user click

Is it possible to redirect an iFrame to a different HTML page when clicked by the user? I have an iFrame that is essentially an HTML page. When I click on the iFrame, I want it to take me to another HTML page. This is my code: h1 { ...

Access a specific element within an array using Handlebars.js

After converting a CSV to JSON, I have data that looks like this: [["Year","Make","Model","Description","Price"],["1997","Ford","E350","ac, abs, moon","3000.00"],["1999","Chevy","Venture \"Extended Edition\"","","4900.00"],["1999","Chevy","Ventu ...

Retrieve the index of the item that has been selected in a dropdown list

<select ng-click="getIndex($index)" size="14" ng-model="playlist.fileSelected" ng-options="saveFile for saveFile in playlist.playlist"></select> When I try to access $index, it shows up as undefined. Is there a way to retrieve the index of the ...

Discover products that contain at least one element from an array and do not possess any elements outside of the array

I've been attempting to create a sophisticated mongo query, but after numerous failed attempts, I've reached out for assistance. Consider the following documents: { // Item 1 name: 'Northeastern Braids', author: 'Daia ...

Issue encountered with Mongodb: Unable to load shared libraries due to missing file libboost_thread.so.1.54.0. The shared object file cannot be opened as it does not exist in the directory

I'm currently in the process of connecting MongoDb with Qt c++. While building it, I encountered some information that seemed harmless: :-1: warning: libboost_system.so.1.54.0, needed by /usr/local/lib/libboost_thread.so, may conflict with libb ...

Concealing my menu with overflow-x: hidden on the body is not an option

Despite setting overflow-x: hidden on the body element, I'm still experiencing horizontal scrolling and can't seem to find a solution. I've searched online for solutions without success. That's why I'm reaching out here in hopes o ...