Заполнение одной ссылки на идентификатор объекта после агрегирования с MongoDB и mongoose

#javascript #node.js #mongodb #mongoose #aggregation-framework

#javascript #node.js #mongodb #mongoose #агрегация-фреймворк

Вопрос:

Я пытаюсь заполнить после агрегирования и подсчета.

Это мои модели:

Журнал пользователя

 const UserLog = new Schema(
  {
    title: {
      type: String,
      required: true,
      trim: true,
    },
    article: {
      type: mongoose.Schema.ObjectId,
      ref: 'Article',
      required: true,
    },
    user: {
      type: mongoose.Schema.ObjectId,
      ref: 'User',
      required: true,
    },
  },
  { timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
);
 

Статья

 const Article = new Schema(
  {
    title: {
      type: String,
      required: true,
      trim: true,
    },
    content: {
      type: String,
      required: true,
    },
  },
  { timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
);
 

И я выполняю запрос, подобный этому:

 export const getCountByArticle = async () => {
  const articles = await UserLog.aggregate([
    {
      $group: { _id: '$article', count: { $sum: 1 } },
    },
  ]);
  return articles;
};
 

Запрос возвращает следующее:

 [
        {
            "_id": "5fcbc12dd895b528289723e6",
            "count": 1
        },
        {
            "_id": "5fccefc375c47a3fd49c083d",
            "count": 2
        }
    ],
 

Проблема в том, что я хочу «заполнить» поле _id фактической статьей. Я пробовал $lookup, но это возвращает массив со всеми статьями, а я этого не хочу. Расслабиться у меня тоже не получается. Under — это то, каким я на самом деле хочу видеть результат.

 [
        {
            "_id": "5fcbc12dd895b528289723e6",
            "title": "Title",
            "content": "contentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontent",
            "count": 1
        },
        {
            "_id": "5fccefc375c47a3fd49c083d",
            "title": "Title",
            "content": "contentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontent",
            "count": 2
        }
    ],
 

Я очень надеюсь, что кто-нибудь сможет мне в этом помочь. Заранее благодарю.

Ответ №1:

Вы можете добавить $lookup шаг конвейера после $group этапа в вашей агрегированной операции, который выполняет аналогичную работу с заполнением и изменением формы вашего потока документов Mongoose, используя $mergeObjects в $replaceRoot для объединения объединенных документов из массива $group и $lookup:

 export const getCountByArticle = async () => {
    const articles = await UserLog.aggregate([
        { $group: { 
            _id: '$article', count: { $sum: 1 } 
        } },
        { $lookup: {
            from: 'articles',
            localField: '_id',    
            foreignField: '_id',  
            as: 'articles'
        } },
        { $replaceRoot: { 
            newRoot: { 
                $mergeObjects: [ 
                    { $arrayElemAt: [ '$articles', 0 ] }, 
                    '$ROOT' 
                ] 
            } 
        } },
        { $project: { articles: 0 } }
    ]).exec();
  
    return articles;
};
 

Ответ №2:

Использовать $lookup для MongoDB> 3.2

 { 
   "$lookup" : {
        from: "name of lookup collection",
        localField: "field in the input collection",
        foreignField: "field in the lookup collection",
        as: "field name for the output documents"
     }
 }