Фильтр коллекции по связанному полю ObjectId - PullRequest
0 голосов
/ 18 марта 2020

СМОТРЕТЬ РЕДАКТИРОВАТЬ ВНУТРИ ВОПРОСА.

У меня есть Node.js Express веб-приложение, использующее MongoDB и Mon goose с коллекциями для статей и комментариев. У них есть ассоциация «один ко многим», где одна статья может иметь много комментариев. Схема модели mon goose выглядит следующим образом:

// models/article
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
  title: { type: String },
  content: { type: String },
}, {timestamps: true});
module.exports = mongoose.model('Article', articleSchema);

и

// models/comment.js
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
  content: { type: String },
  article: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' },
}, {timestamps: true});
module.exports = mongoose.model('Comment', commentSchema);

У меня есть маршрут с параметром для идентификатора статьи

// routes.js
router.get('/articles/:articleId/comments', commentsController.list);

И контроллер с функцией обратного вызова для запроса базы данных и возврата комментариев с заданным идентификатором статьи. Он использует метод фильтрации mon goose find () по идентификатору статьи, взятому из параметра route.

// controllers/commentsController.js
exports.list = (req, res, next) => {
  Comment.find({ article: req.params.articleId })
  .exec((err, comments) => {
    res.render('comments/list', { title: 'Comments', comments: comments });
  });
};

Но это не дает никаких результатов. Просто экспериментируя, я вижу, что req.params.articleId - это строка, а любой comment.article - это объект, поэтому они соответствуют свободному сравнению ==, но не строгому сравнению ===, если я не конвертирую comment.article.toString () , Во всяком случае, как правильно сделать такой запрос. Все мои попытки потерпели неудачу.


РЕДАКТИРОВАТЬ: Я нашел проблему. Код выше, как и должно быть. Проблема должна быть связана с тем, как я высеял БД, что я сделал непосредственно в MongoDB. Я удалил все эти записи и просто добавил их из приложения, и это работает с кодом выше.

1 Ответ

1 голос
/ 18 марта 2020

Один из способов добиться этого - добавить комментарии к модели вашей статьи.

const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
  title: { type: String },
  content: { type: String },
  comments: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Comment'
    }
  ]
}, {timestamps: true});

articleSchema.set('toJSON', {
  transform: (document, returnedObject) => {
    const article = returnedObject

    article.id = article._id.toString()
    delete article._id
  }
})

module.exports = mongoose.model('Article', articleSchema);

Затем получить комментарии одним из следующих способов:

const router = require('express').Router()

const Article = require('../models/article')
const Comment = require('../models/comment')

// article with comments
router.get('/:id', async (request, response, next) => {
  try {
    const article = await Article.findById(request.params.id)
      .populate(
        'comments', {
          content: 1
        }
      )

    response.json(article.toJSON())
  } catch (err) {
    console.log(err)
  }
})

// list of comments belonging to an article
router.get('/:id/comments', async (request, response, next) => {
  try {
    const article = await Article.findById(request.params.id)

    if (!article) {
      response.status(404).json({ error: 'invalid request' })
    }

    const comments = await Comment.find({ article: request.params.id })
      .populate(
        'article', {
          title: 1
        }
      )

    response.json(comments.map(comment => comment.toJSON()))
  } catch (err) {
    console.log(err)
  }
})

module.exports = router
...