MongoDB Запрос из нескольких моделей / схем и возврат в одно поле - PullRequest
0 голосов
/ 21 января 2019

Я использую Nodejs и MongoDB , mongoose и expressjs, создаю Блог API с схемами пользователей, статей, лайков и комментариев. Ниже приведены схемы, которые я использую.


    const UsersSchema = new mongoose.Schema({
      username:        { type: String },
      email:           { type: String },
      date_created:    { type: Date },
      last_modified:   { type: Date }
    });


    const ArticleSchema = new mongoose.Schema({
      id:              { type: String, required: true },
      text:            { type: String, required: true }, 
      posted_by:       { type: Schema.Types.ObjectId, ref: 'User', required: true },
      images:          [{ type: String }],
      date_created:    { type: Date },
      last_modified:   { type: Date }
    });


    const CommentSchema = new mongoose.Schema({
      id:             { type: String, required: true },
      commented_by:   { type: Schema.Types.ObjectId, ref: 'User', required: true },
      article:        { type: Schema.Types.ObjectId, ref: 'Article' },
      text:           { type: String, required: true },
      date_created:   { type: Date },
      last_modified:  { type: Date } 
    });

Что мне действительно нужно, так это когда я * получаю сборник статей * Я также хочу собрать количество комментариев для каждой статьи. Как я могу запросить монго?

1 Ответ

0 голосов
/ 23 января 2019

Поскольку вам нужно запросить более одной коллекции, вы можете использовать агрегацию MongoDB.

Здесь: https://docs.mongodb.com/manual/aggregation/

Пример:

Article
  .aggregate(
    {
      $lookup: {
        from: '<your comments collection name',
        localField: '_id',
        foreignField: 'article',
        as: 'comments'
      }
    },
    {
      $project: {
        comments: '$comments.commented_by',
        text: 1,
        posted_by: 1,
        images: 1,
        date_created: 1,
        last_modified: 1
      }
    },
    {
      $project: {
        hasCommented: {
          $cond: {
            if: { $in: [ '$comments', '<user object id>' ] },
            then: true,
            else: false
          }
        },
        commentsCount: { $size: '$comments' },
        text: 1,
        posted_by: 1,
        images: 1,
        date_created: 1,
        last_modified: 1
      }
    }
  )

Агрегирование стало немного большим, но позвольте мне попытаться объяснить: Сначала нам нужно отфильтровать комментариев после $lookup. Таким образом, мы $unwind их, в результате чего каждая статья содержит только один объект комментария, поэтому мы можем фильтровать, используя $match (это этап фильтрации, он работает так же, как <Model>.find(). После фильтрации желаемых пользовательских комментариев мы $group все снова, $sum: 1 для каждого комментария, используя в качестве группы _id, _id статьи. И мы получаем результат $first для $text, $images и т. д. Позже мы $project все, но теперь мы добавляем hasCommented с $cond, просто сделав: если $comments больше 0 (пользователь прокомментировал, значит, это будет true, иначе false.

Среда агрегации MongoDB - это круто, и вы можете делать с ней практически все, что захотите. Но имейте в виду, что некоторые вещи могут стоить больше, чем другие, всегда читайте ссылку.

...