Самый эффективный способ условного возврата значений из заполненных моделей с использованием Mon goose и GraphQL? - PullRequest
0 голосов
/ 29 мая 2020

Моя цель - условно вернуть значения модели на основе данных, полученных из самих моделей после заполнения.

Это мое текущее решение:

const bcrypt = require("bcryptjs")
const jwt = require("jsonwebtoken")
const moment = require("moment")

const User = require("../../models/user")
const Post = require("../../models/post")

const { checkAuthorSettings, checkFollowingAuthorSettings } = require('../../shared/utility')

login: async ({ email, password }) => {
  try {
    const user = await User.findOne({ email }).populate([
      {
        path: 'posts',
        model: 'Post',
        populate: [
          {
            path: 'author',
            model: 'User',
          },
          {
            path: 'comments',
            model: 'Comment',
            populate: {
              path: 'author',
              model: 'User',
            },
          },
        ],
      },
      {
        path: 'following',
        model: 'User',
        populate: {
          path: 'posts',
          model: 'Post',
          populate: [
            {
              path: 'author',
              model: 'User',
            },
            {
              path: 'comments',
              model: 'Comment',
              populate: {
                path: 'author',
                model: 'User',
              },
            },
          ],
        },
      },
      {
        path: 'favourites',
        model: 'Post',
        populate: [
          {
            path: 'author',
            model: 'User',
          },
          {
            path: 'comments',
            model: 'Comment',
            populate: {
              path: 'author',
              model: 'User',
            },
          },
        ],
      },
    ])

    if (!user) throw new Error("An Account by that Email was not found!")
    if (!password) throw new Error("Please enter your password")

    const passIsValid = bcrypt.compareSync( password, user.password )
    if (!passIsValid) throw new Error("Incorrect Password")

    const token = jwt.sign(
      { 
        _id: user._id, 
        email: user.email,
      }, 
      `${process.env.JWT_SECRET}`, 
      { expiresIn: "1h" }
    )

    user.status = "online"
    user.logged_in_at = moment().format()
    await user.save()

    return {
      ...user._doc,
      token,
      token_expiry: 1,
      email: user.settings.display_email ? user.email : "",
      website: user.settings.display_website ? user.website : "",
      password: null,
      posts: await checkAuthorSettings(user.posts),
      following: await checkFollowingAuthorSettings(user.following),
      favourites: await checkAuthorSettings(user.favourites),
      info: JSON.stringify(user._doc.info),
      geolocation: JSON.stringify(user._doc.geolocation),
      settings: JSON.stringify(user._doc.settings),
    }
  } catch (err) {
    throw err
  }
},

утилита. js:

const checkAuthorSettings = array => {
  return array.map(post => {
    return {
      ...post._doc,
      author: {
        ...post._doc.author._doc,
        email: post._doc.author._doc.settings.display_email ? post._doc.author._doc.email : "",
        website: post._doc.author._doc.settings.display_website ? post._doc.author._doc.website : "",
      }
    }
  })
}

const checkFollowingAuthorSettings = array => {
  return array.map(followed => {
    return {
      ...followed._doc,
      posts: checkAuthorSettings(followed.posts)
    }
  })
}

exports.checkAuthorSettings = checkAuthorSettings
exports.checkFollowingAuthorSettings = checkFollowingAuthorSettings

Я сейчас просматриваю каждый массив в User, что, как мне кажется, далеко не самый эффективный способ добиться этого.

Есть ли у кого-нибудь лучшее решение, чем это?

1 Ответ

1 голос
/ 29 мая 2020

Вы можете использовать virtuals, есть много способов реализовать виртуалы, если вы хотите заменить поле email напрямую, вы можете использовать геттеры

Например,


const AuthorSchema = new Schema({
// other fields
  email: String,
}, {
  toObject: { getters: true }
})

AuthorSchema.path('email').get(function(email) {
  return this.get('settings.display_email') ? email : ''
})

Затем, когда вы вызываете .toObject() в документе, вместо этого вы получите значение virtual.

...