Пн goose совокупность и количество лайков - PullRequest
0 голосов
/ 19 апреля 2020

У меня запрос, относящийся к пн goose агрегации. Я пытался получить данные о пользователях вместе со счетчиками лайков и лайков отдельно, а также с их отношениями, но я не смог добиться успеха.

Вот мой сценарий, у меня есть таблица пользователей и таблица реакций. Таблица пользователей содержит данные о пользователях, а таблица реакций содержит данные о пользователях, а также дополнительную информацию о том, кому понравился пользователь. В моей схеме это тип, например: type = 'like' или love, поэтому мне нужно получить данные пользователя вместе с количеством лайков. Я новичок в MongoDB.

Вот мой код:

Схема пользователя

// Importing Node packages required for schema
const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const validateEmail = function(email) {
  const re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
  return re.test(email)
};
//= ===============================
// User Schema
//= ===============================
const UserSchema = new Schema({
  email: {
    type: String,
    trim: true,
    lowercase: true,
  },
  reactions : [
    { type: Schema.Types.ObjectId, ref: 'ProfileReaction' }
  ],
},
  {
    timestamps: true
  }
);


module.exports = mongoose.model('User', UserSchema);

Схема реакции

const mongoose = require('mongoose'),
  Schema = mongoose.Schema;

  const ProfileReactionSchema = new Schema({
    likedBy: { 
      type: Schema.Types.ObjectId, 
      ref: 'User',
      required: true,
      index: true
    },
    user: { 
        type: Schema.Types.ObjectId, 
        ref: 'User',
        required: true,
        index: true
      },
    type: {
      type: String,
      required: true,
    },
  },
    {
      timestamps: true // Saves createdAt and updatedAt as dates. createdAt will be our timestamp.
    }
);

  module.exports = mongoose.model('ProfileReaction', ProfileReactionSchema);

То, что я действительно хочу, это что-то вроде ниже

{
   _id: '1234',
   email: 'xyz@gmail.com',
   reactions: [
      {
         _id: '1235',
         likedBy: {...},
         user: {...},
         type: 'like'
      },
      {
         _id: '1236',
         likedBy: {...},
         user: {...},
         type: 'love'
      }
   ],
   noOfLikes: 1,
   noOfLoves: 1
}

То, что я пробовал до сих пор, но это дает мне только отношения, но я не получаю счет любит и любит. Но мне нужно, чтобы они оба любили считать, любили считать и отношения

const user = await User.findOne({$or: [
    req.params.id.match(/^[0-9a-fA-F]{24}$/) ? {_id: mongoose.Types.ObjectId(req.params.id)}
    : {uid: req.params.id}
    ]}).populate([
      {
        path: 'reactions',
        model: 'ProfileReaction',
        populate: [
          {
            path: 'likedBy',
            model: 'User'
          }
        ]
      }
    ]);

Я использую версию mongoose v5.6.10.

1 Ответ

1 голос
/ 19 апреля 2020

Вы можете использовать ниже $lookup агрегирование

User.aggregate([
  { "$match": {
    "$or": [
      req.params.id.match(/^[0-9a-fA-F]{24}$/)
        ? { "_id": mongoose.Types.ObjectId(req.params.id) }
        : { "uid": req.params.id }
    ]
  }},
  { "$lookup": {
    "from": ProfileReaction.collection.name,
    "let": { "reactions": "$reactions" },
    "pipeline": [
      { "$match": {
        "$expr": { "$in": ["$_id", "$$reactions"] },
        "type": "like"
      }}
    ],
    "as": "likeReactions"
  }},
  { "$lookup": {
    "from": ProfileReaction.collection.name,
    "let": { "reactions": "$reactions" },
    "pipeline": [
      { "$match": {
        "$expr": { "$in": ["$_id", "$$reactions"] },
        "type": "love"
      }}
    ],
    "as": "loveReactions"
  }},
  { "$addFields": {
    "noOfLikes": { "$size": "$likeReactions" },
    "noOfLoves": { "$size": "$loveReactions" }
  }}
])
...